Пример #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;
}
Пример #2
0
static int start_srtp(struct menc_st *st, const char *suite)
{
	crypto_policy_t policy;
	err_status_t e;

	if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_32)) {
		crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy);
	}
	else if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_80)) {
		crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy);
	}
	else {
		DEBUG_WARNING("unknown SRTP crypto suite (%s)\n", suite);
		return ENOENT;
	}

	/* transmit policy */
	st->policy_tx.rtp = policy;
	st->policy_tx.rtcp = policy;
	st->policy_tx.ssrc.type = ssrc_any_outbound;
	st->policy_tx.key = st->key_tx;
	st->policy_tx.next = NULL;

	/* receive policy */
	st->policy_rx.rtp = policy;
	st->policy_rx.rtcp = policy;
	st->policy_rx.ssrc.type = ssrc_any_inbound;
	st->policy_rx.key = st->key_rx;
	st->policy_rx.next = NULL;

	/* allocate and initialize the SRTP session */
	e = srtp_create(&st->srtp_tx, &st->policy_tx);
	if (e != err_status_ok) {
		DEBUG_WARNING("srtp_create TX failed (%H)\n",
			      errstatus_print, e);
		return EPROTO;
	}

	e = srtp_create(&st->srtp_rx, &st->policy_rx);
	if (err_status_ok != e) {
		DEBUG_WARNING("srtp_create RX failed (%H)\n",
			      errstatus_print, e);
		return EPROTO;
	}

	/* use SRTP for this stream/session */
	st->use_srtp = true;

	return 0;
}
Пример #3
0
JNIEXPORT jint JNICALL Java_org_theonionphone_protocol_SrtpProtocol_initReceiver
	(JNIEnv *env, jobject obj, jint ssrc, jbyteArray keyByteArray, jbyteArray saltByteArray) {

	srtp_policy_t policy;
	char key[SRTP_KEY_SIZE];

	// copy key and salt to an array needed by srtp
	(*env)->GetByteArrayRegion(env, keyByteArray, 0, KEY_SIZE, key);
	(*env)->GetByteArrayRegion(env, saltByteArray, 0, SALT_SIZE, key + KEY_SIZE);

	//set up crypto policies
	crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
	crypto_policy_set_rtcp_default(&policy.rtcp);

	policy.ssrc.type  = ssrc_specific;
	policy.ssrc.value = ssrc;
	policy.key  = (uint8_t *) key;
	policy.next = NULL;
	policy.rtp.sec_serv = sec_serv_conf_and_auth;
	policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */

	//create an srtp stream
	srtpContextRecv = malloc(sizeof(srtp_t*));
		if(srtpContextRecv == NULL) {
			return 69;
		}
	err_status_t status = srtp_create(srtpContextRecv, &policy);

	return status;
}
Пример #4
0
RefPtr<SrtpFlow> SrtpFlow::Create(int cipher_suite,
                                           bool inbound,
                                           const void *key,
                                           size_t key_len) {
  nsresult res = Init();
  if (!NS_SUCCEEDED(res))
    return NULL;

  RefPtr<SrtpFlow> flow = new SrtpFlow();

  if (!key) {
    MOZ_MTLOG(PR_LOG_ERROR, "Null SRTP key specified");
    return NULL;
  }

  if (key_len != SRTP_TOTAL_KEY_LENGTH) {
    MOZ_MTLOG(PR_LOG_ERROR, "Invalid SRTP key length");
    return NULL;
  }

  srtp_policy_t policy;
  memset(&policy, 0, sizeof(srtp_policy_t));

  // Note that we set the same cipher suite for RTP and RTCP
  // since any flow can only have one cipher suite with DTLS-SRTP
  switch (cipher_suite) {
    case SRTP_AES128_CM_HMAC_SHA1_80:
      MOZ_MTLOG(PR_LOG_DEBUG, "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_80");
      crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
      crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
      break;
    case SRTP_AES128_CM_HMAC_SHA1_32:
      MOZ_MTLOG(PR_LOG_DEBUG, "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_32");
      crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
      crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // 80-bit per RFC 5764
      break;                                                   // S 4.1.2.
    default:
      MOZ_MTLOG(PR_LOG_ERROR, "Request to set unknown SRTP cipher suite");
      return NULL;
  }
  // This key is copied into the srtp_t object, so we don't
  // need to keep it.
  policy.key = const_cast<unsigned char *>(
      static_cast<const unsigned char *>(key));
  policy.ssrc.type = inbound ? ssrc_any_inbound : ssrc_any_outbound;
  policy.ssrc.value = 0;
  policy.ekt = NULL;
  policy.window_size = 0;      // Use the default value.
  policy.allow_repeat_tx = 0;  // TODO([email protected]): revisit?
  policy.next = NULL;

  // Now make the session
  err_status_t r = srtp_create(&flow->session_, &policy);
  if (r != err_status_ok) {
    MOZ_MTLOG(PR_LOG_ERROR, "Error creating srtp session");
    return NULL;
  }

  return flow;
}
Пример #5
0
bool SrtpChannel::configureSrtpSession(srtp_t *session, const char* key,
        enum TransmissionType type) {
    srtp_policy_t policy;
    memset(&policy, 0, sizeof(policy));
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    if (type == SENDING) {
        policy.ssrc.type = ssrc_any_outbound;
    } else {

        policy.ssrc.type = ssrc_any_inbound;
    }

    policy.ssrc.value = 0;
    policy.window_size = 1024;
    policy.allow_repeat_tx = 1;
    policy.next = NULL;
    //ELOG_DEBUG("auth_tag_len %d", policy.rtp.auth_tag_len);

    gsize len = 0;
    uint8_t *akey = (uint8_t*) g_base64_decode((gchar*) key, &len);
    ELOG_DEBUG("set master key/salt to %s/", octet_string_hex_string(akey, 16));
    // allocate and initialize the SRTP session
    policy.key = akey;
    int res = srtp_create(session, &policy);
    if (res!=0){
      ELOG_ERROR("Failed to create srtp session with %s, %d", octet_string_hex_string(akey, 16), res);
    }
    return res!=0? false:true;
}
Пример #6
0
double
srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) {
  srtp_t srtp;
  srtp_hdr_t *mesg;  
  int i;
  clock_t timer;
  int num_trials = 100000;
  int len;
  uint32_t ssrc;
  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);
  }

  /*
   * if the ssrc is unspecified, use a predetermined one
   */
  if (policy->ssrc.type != ssrc_specific) {
    ssrc = 0xdeadbeef;
  } else {
    ssrc = policy->ssrc.value;
  }

  /*
   * create a test packet
   */
  mesg = srtp_create_test_packet(msg_len_octets, ssrc);
  if (mesg == NULL)
    return 0.0;   /* indicate failure by returning zero */
  
  timer = clock();
  for (i=0; i < num_trials; i++) {
    err_status_t status;
    len = msg_len_octets + 12;  /* add in rtp header length */
    
    /* srtp protect message */
    status = srtp_protect(srtp, mesg, &len);
    if (status) {
      printf("error: srtp_protect() failed with error code %d\n", status);
      exit(1);
    }

    /* increment message number */
    mesg->seq = htons(ntohs(mesg->seq) + 1);

  }
  timer = clock() - timer;

  free(mesg);
  
  return (double) (msg_len_octets) * 8 *
                  num_trials * CLOCKS_PER_SEC / timer;   
}
Пример #7
0
trtp_srtp_set_crypto(struct trtp_manager_s* rtp_mgr, const char* crypto_line, int32_t idx)
{
	//e.g. 2 F8_128_HMAC_SHA1_80 inline:MTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5QUJjZGVm|2^20|1:4;inline:QUJjZGVmMTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5|2^20|2:4"
	trtp_srtp_ctx_xt* srtp_ctx;
	int ret;
	uint8_t *key_bin;
	err_status_t srtp_err;
	int32_t tag, crypto_type;
	char key_str[SRTP_MAX_KEY_LEN + 1];
	
	memset(key_str, 0, sizeof(key_str));

	if((ret = trtp_srtp_match_line(crypto_line, &tag, &crypto_type, key_str, sizeof(key_str) - 1))){
		return ret;
	}

	srtp_ctx = &rtp_mgr->srtp_contexts[idx][crypto_type];
	ret = trtp_srtp_ctx_deinit(srtp_ctx);

	srtp_ctx->tag = tag;
	srtp_ctx->crypto_type = (trtp_srtp_crypto_type_t)crypto_type;
	memcpy(srtp_ctx->key_str, key_str, sizeof(srtp_ctx->key_str));
	
	switch(srtp_ctx->crypto_type){
		case HMAC_SHA1_80:
			{
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtp);
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp);
				if(idx == TRTP_SRTP_LINE_IDX_REMOTE){
					trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32]);
					rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].tag = srtp_ctx->tag;
				}
				break;
			}
		case HMAC_SHA1_32:
			{
				crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->policy.rtp);
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); // RTCP always 80
				if(idx == TRTP_SRTP_LINE_IDX_REMOTE){
					trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80]);
					rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].tag = srtp_ctx->tag;
				}
				break;
			}
	}

	key_bin = (unsigned char*)srtp_ctx->key_bin;
	tsk_base64_decode((const uint8_t*)srtp_ctx->key_str, tsk_strlen(srtp_ctx->key_str), (char**)&key_bin);
	srtp_ctx->policy.key = key_bin;
	srtp_ctx->policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
	if((srtp_err = srtp_create(&srtp_ctx->session, &srtp_ctx->policy)) != err_status_ok){
		TSK_DEBUG_ERROR("srtp_create() failed: %d", srtp_err);
		return -3;
	}
	srtp_ctx->initialized = tsk_true;
	return 0;
}
Пример #8
0
void * sender_thread (void *arg)
{
    err_status_t status;
    thread_parms_t *tp = (thread_parms_t*)arg;
    rtp_sender_t snd[NUM_SSRC_PER_THREAD];
    int cnt = 0;
    int i;
    srtp_ctx_t *srtp_ctx = NULL;

    printf("\nStarting sender thread (port: %d  base-ssrc: %x  stream_cnt: %d)\n",
           tp->port, tp->ssrc, tp->stream_cnt);

    /* initialize sender's rtp and srtp contexts */
    status = srtp_create(&srtp_ctx, tp->policy);
    if (status) {
        fprintf(stderr,
                "error: srtp_create() failed with code %d\n",
                status);
        exit(1);
    }

    /* now add the streams on the session */
    for (i = 0; i < tp->stream_cnt; i++) {
        rtp_sender_init(&snd[i], tp->sock, tp->name, tp->ssrc);
        snd[i].srtp_ctx = srtp_ctx;
        status = srtp_add_stream(snd[i].srtp_ctx, tp->policy);
        if (status) {
            fprintf(stderr,
                    "error: srtp_add_stream() failed with code %d\n",
                    status);
            exit(1);
        }
        tp->policy->ssrc.value++;
        tp->ssrc++;
    }

    while (cnt < THREAD_PKT_CNT) {
        for (i = 0; i < tp->stream_cnt; i++) {
            rtp_sendto(&snd[i], test_data, DATA_LEN);
            cnt++;
            if (cnt % STAT_WINDOW == 0) {
                printf("Thread id %d transmit count is %d\n", tp->thread_num, cnt);
            }
        }
        usleep(SLEEP_LEN);
    }


    /*
     * Clean up the session
     */
    srtp_dealloc(srtp_ctx);

    return NULL;
}
Пример #9
0
int trtp_srtp_set_key_and_salt(trtp_manager_t* rtp_mgr, trtp_srtp_crypto_type_t crypto_type, const void* key, tsk_size_t key_size, const void* salt, tsk_size_t salt_size, int32_t idx)
{
	int ret;
	trtp_srtp_ctx_xt* srtp_ctx;
	err_status_t srtp_err;
	if(!rtp_mgr || !key || !key_size || !salt || !salt_size){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	if((key_size + salt_size) > sizeof(srtp_ctx->key_bin)){
		TSK_DEBUG_ERROR("Invalid [key||salt].len [%u||%u]", key_size, salt_size);
	}

	srtp_ctx = &rtp_mgr->srtp_contexts[idx][0];
	if((ret = trtp_srtp_ctx_deinit(srtp_ctx))){
		return ret;
	}
		
	switch((srtp_ctx->crypto_type = crypto_type)){
		case HMAC_SHA1_80:
		default:
			{
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtp);
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp);
				break;
			}
		case HMAC_SHA1_32:
			{
				crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->policy.rtp);
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); // always 80
				break;
			}
	}

	memcpy(srtp_ctx->key_bin, key, key_size);
#if HAVE_APPEND_SALT_TO_KEY
	append_salt_to_key(srtp_ctx->key_bin, key_size, (void*)salt, salt_size);
#else
	memcpy(&srtp_ctx->key_bin[key_size], salt, salt_size);
#endif
	
	srtp_ctx->policy.key = srtp_ctx->key_bin;
	srtp_ctx->policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
	if((srtp_err = srtp_create(&srtp_ctx->session, &srtp_ctx->policy)) != err_status_ok){
		TSK_DEBUG_ERROR("srtp_create() failed: %d", srtp_err);
		return -3;
	}
	srtp_ctx->initialized = tsk_true;
	return 0;
}
Пример #10
0
int trtp_srtp_ctx_init(trtp_srtp_ctx_xt* ctx, int32_t tag, trtp_srtp_crypto_type_t type, uint32_t ssrc){

	char* key_str = ctx->key_str;
	err_status_t srtp_err;
	tsk_size_t size;
	
	if(!ctx){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	if(ctx->initialized){
		trtp_srtp_ctx_deinit(ctx);
	}

	ctx->tag = tag;
	ctx->crypto_type = type;
	if((srtp_err = crypto_get_random((unsigned char*)ctx->key_bin, sizeof(ctx->key_bin))) != err_status_ok){
		TSK_DEBUG_ERROR("crypto_get_random() failed");
		return -2;
	}
	size = tsk_base64_encode((const uint8_t*)ctx->key_bin, sizeof(ctx->key_bin), &key_str);
	key_str[size] = '\0';

	switch(ctx->crypto_type){
		case HMAC_SHA1_80:
			{
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtp);
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp);
				break;
			}
		case HMAC_SHA1_32:
		default:
			{
				crypto_policy_set_aes_cm_128_hmac_sha1_32(&ctx->policy.rtp);
				crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp); // RTCP always 80
				break;
			}
	}
	
	ctx->policy.key = (unsigned char*)ctx->key_bin;
	ctx->policy.ssrc.type = ssrc_any_outbound;
	ctx->policy.ssrc.value = ssrc;
	if((srtp_err = srtp_create(&ctx->session, &ctx->policy)) != err_status_ok){
		TSK_DEBUG_ERROR("srtp_create() failed");
		return -3;
	}
	ctx->initialized = tsk_true;
	return 0;
}
err_status_t srtp_print_policy(const srtp_policy_t *policy) {
    err_status_t status;
    srtp_t session;

    status = srtp_create(&session, policy);
    if (status)
        return status;
    status = srtp_session_print_policy(session);
    if (status)
        return status;
    status = srtp_dealloc(session);
    if (status)
        return status;
    return err_status_ok;
}
Пример #12
0
JNIEXPORT jint JNICALL Java_org_theonionphone_protocol_SrtpProtocol_initSender
	(JNIEnv *env, jobject obj, jbyteArray keyByteArray, jbyteArray saltByteArray, jint codecType, jint sampleCount,
			jint payloadSizeInBytes, jint rtpPacketSizeInBytes, jint srtpPacketSizeInBytes) {

	srtp_policy_t policy;
	char key[SRTP_KEY_SIZE];
	payloadSize = payloadSizeInBytes;
	rtpPacketSize = rtpPacketSizeInBytes;
	srtpPacketSize = srtpPacketSizeInBytes;

	// copy key and salt to an array needed by srtp
	(*env)->GetByteArrayRegion(env, keyByteArray, 0, KEY_SIZE, key);
	(*env)->GetByteArrayRegion(env, saltByteArray, 0, SALT_SIZE, key + KEY_SIZE);

	//initialize rtp
	err_status_t status = initRtp(&rtpContext, codecType, sampleCount);
	if(status) {
		return status;
	}

	//initialize srtp
	status = srtp_init();
	if(status) {
		return status;
	}

	//set up crypto policies
	crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
	crypto_policy_set_rtcp_default(&policy.rtcp);

	policy.ssrc.type  = ssrc_specific;
	policy.ssrc.value = rtpContext->mSsrc;
	policy.key  = (uint8_t *) key;
	policy.next = NULL;
	policy.rtp.sec_serv = sec_serv_conf_and_auth;
	policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */

	//create an srtp stream
	srtpContextSend = malloc(sizeof(srtp_t*));
	if(srtpContextSend == NULL) {
		return 69;
	}
	status = srtp_create(srtpContextSend, &policy);

	return status;
}
Пример #13
0
err_status_t
srtp_test_remove_stream() { 
  err_status_t status;
  srtp_policy_t *policy_list;
  srtp_t session;
  srtp_stream_t stream;
  /* 
   * srtp_get_stream() is a libSRTP internal function that we declare
   * here so that we can use it to verify the correct operation of the
   * library
   */ 
  extern srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
  

  status = srtp_create_big_policy(&policy_list);
  if (status)
    return status;

  status = srtp_create(&session, policy_list);
  if (status)
    return status;

  /*
   * check for false positives by trying to remove a stream that's not
   * in the session
   */
  status = srtp_remove_stream(session, htonl(0xaaaaaaaa));
  if (status != err_status_no_ctx)
    return err_status_fail;
  
  /* 
   * check for false negatives by removing stream 0x1, then
   * searching for streams 0x0 and 0x2
   */
  status = srtp_remove_stream(session, htonl(0x1));
  if (status != err_status_ok)
    return err_status_fail;
  stream = srtp_get_stream(session, htonl(0x0));
  if (stream == NULL)
    return err_status_fail;
  stream = srtp_get_stream(session, htonl(0x2));
  if (stream == NULL)
    return err_status_fail;  

  return err_status_ok;  
}
Пример #14
0
srtpw_err_status_t srtpw_srtp_create(srtpw_srtp **srtp, srtpw_srtp_policy *srtp_policy)
{
    int status=0;
    /*
     * create a session with a single stream using the default srtp
     * policy and with the SSRC value 0xcafebabe
     */
    srtp_policy_t *policy =(srtp_policy_t *)srtp_policy;
    srtpw_log(err_level_info, "srtpw_srtp_create:  policy:0x%x",policy);
#if 0

    crypto_policy_set_rtp_default(&policy->rtp);
    crypto_policy_set_rtcp_default(&policy->rtcp);
    policy->ssrc.type  = ssrc_specific;
    policy->ssrc.value = 0;
    policy->key  = NULL;
#endif
    policy->next = NULL;

    status = srtp_create((srtp_t *)srtp,policy);
    return status;
}
Пример #15
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;   
}
Пример #16
0
RefPtr<SrtpFlow> SrtpFlow::Create(int cipher_suite,
                                           bool inbound,
                                           const void *key,
                                           size_t key_len) {
  nsresult res = Init();
  if (!NS_SUCCEEDED(res))
    return nullptr;

  RefPtr<SrtpFlow> flow = new SrtpFlow();

  if (!key) {
    CSFLogError(LOGTAG, "Null SRTP key specified");
    return nullptr;
  }

  if (key_len != SRTP_TOTAL_KEY_LENGTH) {
    CSFLogError(LOGTAG, "Invalid SRTP key length");
    return nullptr;
  }

  srtp_policy_t policy;
  memset(&policy, 0, sizeof(srtp_policy_t));

  // Note that we set the same cipher suite for RTP and RTCP
  // since any flow can only have one cipher suite with DTLS-SRTP
  switch (cipher_suite) {
    case SRTP_AES128_CM_HMAC_SHA1_80:
      CSFLogDebug(LOGTAG,
                  "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_80");
      srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
      srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
      break;
    case SRTP_AES128_CM_HMAC_SHA1_32:
      CSFLogDebug(LOGTAG,
                  "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_32");
      srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
      srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // 80-bit per RFC 5764
      break;                                                   // S 4.1.2.
    default:
      CSFLogError(LOGTAG, "Request to set unknown SRTP cipher suite");
      return nullptr;
  }
  // This key is copied into the srtp_t object, so we don't
  // need to keep it.
  policy.key = const_cast<unsigned char *>(
      static_cast<const unsigned char *>(key));
  policy.ssrc.type = inbound ? ssrc_any_inbound : ssrc_any_outbound;
  policy.ssrc.value = 0;
  policy.ekt = nullptr;
  policy.window_size = 1024;   // Use the Chrome value.  Needs to be revisited.  Default is 128
  policy.allow_repeat_tx = 1;  // Use Chrome value; needed for NACK mode to work
  policy.next = nullptr;

  // Now make the session
  srtp_err_status_t r = srtp_create(&flow->session_, &policy);
  if (r != srtp_err_status_ok) {
    CSFLogError(LOGTAG, "Error creating srtp session");
    return nullptr;
  }

  return flow;
}
Пример #17
0
int main (int argc, char *argv[])
{
  struct rtp *session;
  int   rx_port, tx_port, fd;
  uint32_t   read_size, packet_size, number_of_packet;
  uint8_t  buff[BUFFSIZE];
  off_t cur_pos;
  char *ip_addr;
  char filename[1024];
  int c;                        
  struct hostent *h;
  struct utsname myname;
#ifdef HAVE_SRTP
#else
  void *srtp_data;
#endif
  unsigned int extra_len;
  int do_auth = 1, do_encrypt = 1;
  ssize_t readit;
  ssize_t sendit;
  int do_rtcp = false;

  // Setting of default session 
  if(uname(&myname) < 0){
    fprintf(stderr,"uname\n");
    exit(1);
  }
  if((h = gethostbyname(myname.nodename)) == NULL) {
    herror("gethostbyname");
    exit(1);
  }
  ip_addr = strdup(inet_ntoa(*((struct in_addr *)h->h_addr)));
  rx_port = 15002;
  tx_port = 15000;

  // Option
  opterr = 0;
  while((c = getopt(argc, argv, "acdehi:r:t:f:")) != -1){
    switch (c) {
    case 'a':
      do_auth = 0;
      break;
    case 'c':
      do_rtcp = 1;
 	break;
    case 'd':
      dump_pak = true;
 	break;
    case 'e':
      do_encrypt = 0;
      break;
    case 'h':
      printf("Usage: ./test_rtp_client -i <IP_Addr> -r <rx_port> -t <tx_port> -f <filename>\n");
      printf("Default values are as follows...\n");
      printf("ip_addr = %s\n", ip_addr);
      printf("rx_port = %d\n", rx_port);
      printf("tx_port = %d\n", tx_port);
      printf("Filename = %s\n", filename);
      exit(-1);
    case 'i':
      strcpy(ip_addr, optarg);
      break;
    case 'r':
      rx_port = atoi(optarg);
      break;
    case 't':
      tx_port = atoi(optarg);
      break;
    case 'f':
      strcpy(filename,optarg);
      break;
    case '?':
      printf("usage: ./test_rtp_client -i <IP_Addr> -r <rx_port> -t <tx_port> -f <filename>\n");
      exit(1);
    }
  }
  if (optind < argc) {
    for(; optind < argc; optind++) {
      printf("error->%s(#%d): put -[i|r|t|f] \n", argv[optind],optind-1);
    }
    exit(1);
  }

  // display session information
  printf("\n-Session Information-\n");
  printf("  ip_addr = %s\n", ip_addr);
  printf("  rx_port = %d\n", rx_port);
  printf("  tx_port = %d\n", tx_port);
  printf("  filename = %s\n", filename);
  printf("Press Return key...");
  //  getchar();

  // Open Original File to compare with received file
  if((fd = open(filename, O_RDONLY)) == -1){
    perror(filename);
    exit(1);
  }
  rtp_stream_params_t rsp;
  rtp_default_params(&rsp);
  rsp.rtp_addr = ip_addr;
  rsp.rtp_rx_port = rx_port;
  rsp.rtp_tx_port = tx_port;
  rsp.rtp_ttl = TTL;
  rsp.rtcp_bandwidth = RTCP_BW;
  rsp.rtp_callback = c_rtp_callback;
  rsp.transmit_initial_rtcp = 1;
  if ( (session = rtp_init_stream(&rsp) ) == NULL){
    exit(-1);
  }
  rtp_set_my_ssrc(session,OUR_SSRC);

#ifdef HAVE_SRTP
	/////////// start will
	//set NULL security services
  //uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
  srtp_policy_t policy;
  char key[64];
  char keystr[128];
  uint ix;
#if 1
  strcpy(keystr, "c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451");
  hex_string_to_octet_string(key, keystr, 60);
#else
  memset(key, 0, sizeof(key));
#endif

  for (ix = 0; ix < 30; ix++) {
    printf("%02x ", key[ix]);
  }
  printf("\n");
#if 0
  // NULL cipher
  policy.key                 =  (uint8_t *) key;
  policy.ssrc.type           = ssrc_any_outbound; //ssrc_specific;
  policy.ssrc.value          = 0x96;//OUR_SSRC;
  policy.rtp.cipher_type     = NULL_CIPHER;
  policy.rtp.cipher_key_len  = 0; 
  policy.rtp.auth_type       = NULL_AUTH;
  policy.rtp.auth_key_len    = 0;
  policy.rtp.auth_tag_len    = 0;
  policy.rtp.sec_serv        = sec_serv_none;
  policy.rtcp.cipher_type    = NULL_CIPHER;
  policy.rtcp.cipher_key_len = 0; 
  policy.rtcp.auth_type      = NULL_AUTH;
  policy.rtcp.auth_key_len   = 0;
  policy.rtcp.auth_tag_len   = 0;
  policy.rtcp.sec_serv       = sec_serv_none;   
  policy.next                = NULL;
#else
  //confidentiality only, no auth
  crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
  crypto_policy_set_rtcp_default(&policy.rtcp);
  policy.ssrc.type  = ssrc_any_outbound;
  policy.key  = (uint8_t *) key;
  policy.next = NULL;
  policy.rtp.sec_serv = sec_serv_conf;//sec_servs;
  policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */
#endif
  err_status_t status;

  printf("ABOUT TO SRTP_INIT\n");
  status = srtp_init();
  if (status) {
    printf("error: srtp initialization failed with error code %d\n", status);
    exit(1);
  }
  printf("ABOUT TO SRTP_CREAT\n");
  srtp_ctx_t *srtp_ctx = NULL;
  status = srtp_create(&srtp_ctx, &policy);
  if (status) {
    printf("error: srtp_create() failed with code %d\n", status);
    exit(1);
  }
  printf("DONE WITH SRTP_CREATE\n");
  extra_len = 0;
#else

  extra_len = 0;
  srtp_data = NULL;
#endif
  rtp_encryption_params_t params;
  params.rtp_encrypt = ENCRYPT_FUNCTION;
  params.rtcp_encrypt = RTCP_ENCRYPT_FUNCTION;
  params.rtp_decrypt = DECRYPT_FUNCTION;
  params.rtcp_decrypt = RTCP_DECRYPT_FUNCTION;
  params.userdata = srtp_data;
  params.rtp_auth_alloc_extra = params.rtcp_auth_alloc_extra = 0;

  rtp_set_encryption_params(session, &params);

  if (do_rtcp) {
    rtcp_file = fopen("server.rtcp", FOPEN_WRITE_BINARY);
  }

  cur_pos = 0;
  packet_size = 64;
  number_of_packet = 0;
  while(1) {
    // change BUFFSIZE to be an incrementing value from 64 to 1450
    if(packet_size > 1450)
      packet_size = 725;
    readit = read(fd, buff, packet_size);
    if (readit < 0) {
      perror("file read");
      exit(1);
    }
    read_size = readit;
    //int buflen = readit;
    if (read_size == 0) break;
    //printf("about to protect\n");
#if 0
    sendit = 
      rtp_send_data(session,
		    cur_pos,
		    97,//pt
		    0,//m
		    0,//cc 
		    NULL, //csrc[],
		    buff,//data
		    read_size,//data_len
		    NULL,//*extn
		    0,
		    0);
#else
    {
      struct iovec iov[2];
      iov[0].iov_len = read_size % 48;
      if (iov[0].iov_len == 0) iov[0].iov_len = 1;
      iov[0].iov_base = buff;
      iov[1].iov_len = read_size - iov[0].iov_len;
      iov[1].iov_base = buff + iov[0].iov_len;

      sendit = rtp_send_data_iov(session, cur_pos, 97, 0, 0, NULL, 
				 iov, read_size > iov[0].iov_len ? 2 : 1,
				 NULL, 0, 0, 0);
    }
#endif
    if (sendit < 0) {
      printf("rtp_send_data error\n");
      exit(1);
    }
    if (do_rtcp)
      rtp_send_ctrl(session, cur_pos, NULL);
    printf("set timestamp = "U64", size %u\n", cur_pos, read_size);
		
    cur_pos += read_size; 
    packet_size++;
    number_of_packet++;
		
    //rtp_periodic();
    //rtp_send_ctrl(session,cur_pos,NULL);
    rtp_update(session);
    // Some sort of sleep here...
    usleep(2 * 1000);
  }
  
  printf("I've sent %d RTP packets!\n\n", number_of_packet);

  close(fd);
  if (rtcp_file != NULL) 
    fclose(rtcp_file);
  rtp_done(session);
  return 0;
}
Пример #18
0
/**
 * SRTP crypto data ready for the sender or receiver.
 *
 * The ZRTP implementation calls this method right after all SRTP
 * secrets are computed and ready to be used. The parameter points
 * to a structure that contains pointers to the SRTP secrets and a
 * <code>enum Role</code>. The called method (the implementation
 * of this abstract method) must either copy the pointers to the SRTP
 * data or the SRTP data itself to a save place. The SrtpSecret_t
 * structure is destroyed after the callback method returns to the
 * ZRTP implementation.
 *
 * The SRTP data themselves are obtained in the ZRtp object and are
 * valid as long as the ZRtp object is active. TheZRtp's
 * destructor clears the secrets. Thus the called method needs to
 * save the pointers only, ZRtp takes care of the data.
 *
 * The implementing class may enable SRTP processing in this
 * method or delay it to srtpSecertsOn().
 *
 * @param ctx
 *    Pointer to the opaque ZrtpContext structure.
 * @param secrets A pointer to a SrtpSecret_t structure that
 *     contains all necessary data.
 *
 * @param part for which part (Sender or Receiver) this data is
 *     valid.
 *
 * @return Returns false if something went wrong during
 *    initialization of SRTP context, for example memory shortage.
 */
static int32_t ozrtp_srtpSecretsReady (ZrtpContext* ctx, C_SrtpSecret_t* secrets, int32_t part ) {
	srtp_policy_t policy;
	err_status_t srtpCreateStatus;
	err_status_t addStreamStatus;
	OrtpZrtpContext *userData = user_data(ctx);

	ortp_message("ZRTP secrets for %s are ready; auth tag len is %i",
	             (part == ForSender) ? "sender" : "receiver",secrets->srtpAuthTagLen);

	// Get authentication and cipher algorithms in srtp format
	if (secrets->authAlgorithm != zrtp_Sha1) {
		ortp_fatal("unsupported authentication algorithm by srtp");
	}

	if (secrets->symEncAlgorithm != zrtp_Aes) {
		ortp_fatal("unsupported cipher algorithm by srtp");
	}

	/*
	 * Don't use crypto_policy_set_from_profile_for_rtp(), it is totally buggy.
	 */
	memset(&policy,0,sizeof(policy));

	if (secrets->srtpAuthTagLen == 32){
		crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
		crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtcp);
	}else if (secrets->srtpAuthTagLen == 80){
		crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
		crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
	}else{
		ortp_fatal("unsupported auth tag len");
	}

	if (part == ForSender) {
		srtpCreateStatus=srtp_create(&userData->srtpSend, NULL);
		policy.ssrc.type=ssrc_specific;
		policy.ssrc.value=userData->session->snd.ssrc; // us
		policy.key=key_with_salt(secrets, secrets->role);
		addStreamStatus=srtp_add_stream(userData->srtpSend, &policy);
	} else { //if (part == ForReceiver)
		srtpCreateStatus=srtp_create(&userData->srtpRecv, NULL);
		policy.ssrc.type = ssrc_any_inbound; /*we don't know the incoming ssrc will be */
		int32_t peerRole=secrets->role == Initiator ? Responder : Initiator;
		policy.key=key_with_salt(secrets,peerRole);
		addStreamStatus=srtp_add_stream(userData->srtpRecv, &policy);
	}

	ortp_free(policy.key);

	if (srtpCreateStatus != err_status_ok) {
		ortp_error("ZRTP Error %u during creation of SRTP context for %s",
			srtpCreateStatus, (part == ForSender) ? "sender" : "receiver");
		return 0;
	}
	if (addStreamStatus != err_status_ok) {
		ortp_error("ZRTP Error %u during addition of SRTP stream for %s",
			addStreamStatus, (part == ForSender) ? "sender" : "receiver");
		return 0;
	}
	return 1;
}
Пример #19
0
void janus_dtls_srtp_incoming_msg(janus_dtls_srtp *dtls, char *buf, uint16_t len) {
	if(dtls == NULL) {
		JANUS_LOG(LOG_ERR, "No DTLS-SRTP stack, no incoming message...\n");
		return;
	}
	janus_ice_component *component = (janus_ice_component *)dtls->component;
	if(component == NULL) {
		JANUS_LOG(LOG_ERR, "No component, no DTLS...\n");
		return;
	}
	janus_ice_stream *stream = component->stream;
	if(!stream) {
		JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n");
		return;
	}
	janus_ice_handle *handle = stream->handle;
	if(!handle || !handle->agent) {
		JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n");
		return;
	}
	if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT)) {
		JANUS_LOG(LOG_WARN, "[%"SCNu64"] Alert already triggered, clearing up...\n", handle->handle_id);
		return;
	}
	if(!dtls->ssl || !dtls->read_bio) {
		JANUS_LOG(LOG_ERR, "[%"SCNu64"] No DTLS stuff for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
		return;
	}
	janus_dtls_fd_bridge(dtls);
	int written = BIO_write(dtls->read_bio, buf, len);
	JANUS_LOG(LOG_HUGE, "[%"SCNu64"]     Written %d of those bytes on the read BIO...\n", handle->handle_id, written);
	janus_dtls_fd_bridge(dtls);
	/* Try to read data */
	char data[1500];	/* FIXME */
	memset(&data, 0, 1500);
	int read = SSL_read(dtls->ssl, &data, 1500);
	JANUS_LOG(LOG_HUGE, "[%"SCNu64"]     ... and read %d of them from SSL...\n", handle->handle_id, read);
	if(read < 0) {
		unsigned long err = SSL_get_error(dtls->ssl, read);
		if(err == SSL_ERROR_SSL) {
			/* Ops, something went wrong with the DTLS handshake */
			char error[200];
			ERR_error_string_n(ERR_get_error(), error, 200);
			JANUS_LOG(LOG_ERR, "[%"SCNu64"] Handshake error: %s\n", handle->handle_id, error);
			return;
		}
	}
	janus_dtls_fd_bridge(dtls);
	if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_STOP) || janus_is_stopping()) {
		/* DTLS alert triggered, we should end it here */
		JANUS_LOG(LOG_VERB, "[%"SCNu64"] Forced to stop it here...\n", handle->handle_id);
		return;
	}
	if(!SSL_is_init_finished(dtls->ssl)) {
		/* Nothing else to do for now */
		JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Initialization not finished yet...\n", handle->handle_id);
		return;
	}
	if(dtls->ready) {
		/* There's data to be read? */
		JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Any data available?\n", handle->handle_id);
#ifdef HAVE_SCTP
		if(dtls->sctp != NULL && read > 0) {
			JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Sending data (%d bytes) to the SCTP stack...\n", handle->handle_id, read);
			janus_sctp_data_from_dtls(dtls->sctp, data, read);
		}
#else
		if(read > 0) {
			JANUS_LOG(LOG_WARN, "[%"SCNu64"] Data available but Data Channels support disabled...\n", handle->handle_id);
		}
#endif
	} else {
		JANUS_LOG(LOG_VERB, "[%"SCNu64"] DTLS established, yay!\n", handle->handle_id);
		/* Check the remote fingerprint */
		X509 *rcert = SSL_get_peer_certificate(dtls->ssl);
		if(!rcert) {
			JANUS_LOG(LOG_ERR, "[%"SCNu64"] No remote certificate??\n", handle->handle_id);
		} else {
			unsigned int rsize;
			unsigned char rfingerprint[EVP_MAX_MD_SIZE];
			char remote_fingerprint[160];
			char *rfp = (char *)&remote_fingerprint;
			if(handle->remote_hashing && !strcasecmp(handle->remote_hashing, "sha-1")) {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-1 fingerprint of remote certificate...\n", handle->handle_id);
				X509_digest(rcert, EVP_sha1(), (unsigned char *)rfingerprint, &rsize);
			} else {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-256 fingerprint of remote certificate...\n", handle->handle_id);
				X509_digest(rcert, EVP_sha256(), (unsigned char *)rfingerprint, &rsize);
			}
			X509_free(rcert);
			rcert = NULL;
			unsigned int i = 0;
			for(i = 0; i < rsize; i++) {
				g_snprintf(rfp, 4, "%.2X:", rfingerprint[i]);
				rfp += 3;
			}
			*(rfp-1) = 0;
			JANUS_LOG(LOG_VERB, "[%"SCNu64"] Remote fingerprint (%s) of the client is %s\n",
				handle->handle_id, handle->remote_hashing ? handle->remote_hashing : "sha-256", remote_fingerprint);
			if(!strcasecmp(remote_fingerprint, handle->remote_fingerprint ? handle->remote_fingerprint : "(none)")) {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"]  Fingerprint is a match!\n", handle->handle_id);
				dtls->dtls_state = JANUS_DTLS_STATE_CONNECTED;
				dtls->dtls_connected = janus_get_monotonic_time();
			} else {
				/* FIXME NOT a match! MITM? */
				JANUS_LOG(LOG_ERR, "[%"SCNu64"]  Fingerprint is NOT a match! got %s, expected %s\n", handle->handle_id, remote_fingerprint, handle->remote_fingerprint);
				dtls->dtls_state = JANUS_DTLS_STATE_FAILED;
				goto done;
			}
			if(dtls->dtls_state == JANUS_DTLS_STATE_CONNECTED) {
				if(component->stream_id == handle->audio_id || component->stream_id == handle->video_id) {
					/* Complete with SRTP setup */
					unsigned char material[SRTP_MASTER_LENGTH*2];
					unsigned char *local_key, *local_salt, *remote_key, *remote_salt;
					/* Export keying material for SRTP */
					if (!SSL_export_keying_material(dtls->ssl, material, SRTP_MASTER_LENGTH*2, "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) {
						/* Oops... */
						JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, couldn't extract SRTP keying material for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
						goto done;
					}
					/* Key derivation (http://tools.ietf.org/html/rfc5764#section-4.2) */
					if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) {
						local_key = material;
						remote_key = local_key + SRTP_MASTER_KEY_LENGTH;
						local_salt = remote_key + SRTP_MASTER_KEY_LENGTH;
						remote_salt = local_salt + SRTP_MASTER_SALT_LENGTH;
					} else {
						remote_key = material;
						local_key = remote_key + SRTP_MASTER_KEY_LENGTH;
						remote_salt = local_key + SRTP_MASTER_KEY_LENGTH;
						local_salt = remote_salt + SRTP_MASTER_SALT_LENGTH;
					}
					/* Build master keys and set SRTP policies */
						/* Remote (inbound) */
					crypto_policy_set_rtp_default(&(dtls->remote_policy.rtp));
					crypto_policy_set_rtcp_default(&(dtls->remote_policy.rtcp));
					dtls->remote_policy.ssrc.type = ssrc_any_inbound;
					unsigned char remote_policy_key[SRTP_MASTER_LENGTH];
					dtls->remote_policy.key = (unsigned char *)&remote_policy_key;
					memcpy(dtls->remote_policy.key, remote_key, SRTP_MASTER_KEY_LENGTH);
					memcpy(dtls->remote_policy.key + SRTP_MASTER_KEY_LENGTH, remote_salt, SRTP_MASTER_SALT_LENGTH);
#if HAS_DTLS_WINDOW_SIZE
					dtls->remote_policy.window_size = 128;
					dtls->remote_policy.allow_repeat_tx = 0;
#endif
					dtls->remote_policy.next = NULL;
						/* Local (outbound) */
					crypto_policy_set_rtp_default(&(dtls->local_policy.rtp));
					crypto_policy_set_rtcp_default(&(dtls->local_policy.rtcp));
					dtls->local_policy.ssrc.type = ssrc_any_outbound;
					unsigned char local_policy_key[SRTP_MASTER_LENGTH];
					dtls->local_policy.key = (unsigned char *)&local_policy_key;
					memcpy(dtls->local_policy.key, local_key, SRTP_MASTER_KEY_LENGTH);
					memcpy(dtls->local_policy.key + SRTP_MASTER_KEY_LENGTH, local_salt, SRTP_MASTER_SALT_LENGTH);
#if HAS_DTLS_WINDOW_SIZE
					dtls->local_policy.window_size = 128;
					dtls->local_policy.allow_repeat_tx = 0;
#endif
					dtls->local_policy.next = NULL;
					/* Create SRTP sessions */
					err_status_t res = srtp_create(&(dtls->srtp_in), &(dtls->remote_policy));
					if(res != err_status_ok) {
						/* Something went wrong... */
						JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating inbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
						JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_get_srtp_error(res));
						goto done;
					}
					JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created inbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
					res = srtp_create(&(dtls->srtp_out), &(dtls->local_policy));
					if(res != err_status_ok) {
						/* Something went wrong... */
						JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating outbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
						JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_get_srtp_error(res));
						goto done;
					}
					dtls->srtp_valid = 1;
					JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created outbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
				}
#ifdef HAVE_SCTP
				if(component->stream_id == handle->data_id ||
						(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE) &&
						janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_DATA_CHANNELS))) {
					/* FIXME Create SCTP association as well (5000 should be dynamic, from the SDP...) */
					dtls->sctp = janus_sctp_association_create(dtls, handle->handle_id, 5000);
					if(dtls->sctp != NULL) {
						/* FIXME We need to start it in a thread, though, since it has blocking accept/connect stuff */
						GError *error = NULL;
						g_thread_try_new("DTLS-SCTP", janus_dtls_sctp_setup_thread, dtls, &error);
						if(error != NULL) {
							/* Something went wrong... */
							JANUS_LOG(LOG_ERR, "[%"SCNu64"] Got error %d (%s) trying to launch the DTLS-SCTP thread...\n", handle->handle_id, error->code, error->message ? error->message : "??");
						}
						dtls->srtp_valid = 1;
					}
				}
#endif
				dtls->ready = 1;
			}
done:
			if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT) && dtls->srtp_valid) {
				/* Handshake successfully completed */
				janus_ice_dtls_handshake_done(handle, component);
			} else {
				/* Something went wrong in either DTLS or SRTP... tell the plugin about it */
				janus_dtls_callback(dtls->ssl, SSL_CB_ALERT, 0);
				janus_flags_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_CLEANING);
			}
		}
	}
}
Пример #20
0
err_status_t
srtcp_test(const srtp_policy_t *policy) {
  int i;
  srtp_t srtcp_sender;
  srtp_t srtcp_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(&srtcp_sender, policy));

  /* print out policy */
  err_check(srtp_session_print_policy(srtcp_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_rtcp(srtcp_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_rtcp() 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(&srtcp_rcvr, rcvr_policy));
   
  err_check(srtp_unprotect_rtcp(srtcp_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_rtcp(srtcp_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_rtcp(srtcp_sender, hdr, &len));
    
    /* flip bits in packet */
    data[0] ^= 0xff;

    /* unprotect, and check for authentication failure */
    status = srtp_unprotect_rtcp(srtcp_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(srtcp_sender));
  err_check(srtp_dealloc(srtcp_rcvr));

  free(hdr);
  free(hdr2);
  return err_status_ok;
}
Пример #21
0
/* Create a stream in the session
 */
static err_status_t
init_session_stream (GstSrtpDec * filter, guint32 ssrc,
    GstSrtpDecSsrcStream * stream)
{
  err_status_t ret;
  srtp_policy_t policy;
  GstMapInfo map;
  guchar tmp[1];

  memset (&policy, 0, sizeof (srtp_policy_t));

  if (!stream)
    return err_status_bad_param;

  GST_INFO_OBJECT (filter, "Setting RTP policy...");
  set_crypto_policy_cipher_auth (stream->rtp_cipher, stream->rtp_auth,
      &policy.rtp);
  GST_INFO_OBJECT (filter, "Setting RTCP policy...");
  set_crypto_policy_cipher_auth (stream->rtcp_cipher, stream->rtcp_auth,
      &policy.rtcp);

  if (stream->key) {
    gst_buffer_map (stream->key, &map, GST_MAP_READ);
    policy.key = (guchar *) map.data;
  } else {
    policy.key = tmp;
  }

  policy.ssrc.value = ssrc;
  policy.ssrc.type = ssrc_specific;
  policy.window_size = filter->replay_window_size;
  policy.next = NULL;

  /* If it is the first stream, create the session
   * If not, add the stream policy to the session
   */
  if (filter->first_session)
    ret = srtp_create (&filter->session, &policy);
  else
    ret = srtp_add_stream (filter->session, &policy);

  if (stream->key)
    gst_buffer_unmap (stream->key, &map);

  if (ret == err_status_ok) {
    srtp_stream_t srtp_stream;

    srtp_stream = srtp_get_stream (filter->session, htonl (ssrc));
    if (srtp_stream) {
      /* Here, we just set the ROC, but we also need to set the initial
       * RTP sequence number later, otherwise libsrtp will not be able
       * to get the right packet index. */
      rdbx_set_roc (&srtp_stream->rtp_rdbx, stream->roc);
      filter->roc_changed = TRUE;
    }

    filter->first_session = FALSE;
    g_hash_table_insert (filter->streams, GUINT_TO_POINTER (stream->ssrc),
        stream);
  }

  return ret;
}
Пример #22
0
int
evrb_crypto_keys_compute(void* local_ctx, void* distant_ctx, int caller)
{
	srtp_policy_t* loc_policy;
	srtp_policy_t* dist_policy;
	EVRB_CRYPTO* loc = (EVRB_CRYPTO*)local_ctx;
	EVRB_CRYPTO* dist = (EVRB_CRYPTO*)distant_ctx;
	unsigned char *master_key;
	int	master_key_len;

	if(!local_ctx || !distant_ctx)
		return -1;

	loc_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t));
	dist_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t));
	if(!loc_policy || !dist_policy)
		return -1;

	memcpy(loc_policy, &default_policy, sizeof(srtp_policy_t));
	memcpy(dist_policy, &default_policy, sizeof(srtp_policy_t));
	loc_policy->ssrc.type = ssrc_any_outbound;
	dist_policy->ssrc.type = ssrc_any_inbound;

	if (loc->dh == NULL)
	  return -1;

	master_key = dh_compute_key(loc->dh, dist->key, &master_key_len);

#ifndef NDEBUG
	{
	  int i;
	printf("key1=%s\nkey2=%s\n", loc->key, dist->key);
	printf("master_key(%d)=", master_key_len);
	for (i = 0; i < master_key_len; i++)
	  printf("%02x", master_key[i]);
	printf("\n");
	}
#endif
	loc_policy->key = (uint8_t*)malloc(EVRB_KEY_SIZE);
	dist_policy->key = (uint8_t*)malloc(EVRB_KEY_SIZE);

	// TODO: better key derivation
	/* Simmetric keys */
	if (caller)
	  {
	    memcpy(loc_policy->key, master_key, EVRB_KEY_SIZE);
	    memcpy(dist_policy->key, master_key+EVRB_KEY_SIZE, EVRB_KEY_SIZE);
	  }
	else
	  {
	    memcpy(loc_policy->key, master_key+EVRB_KEY_SIZE, EVRB_KEY_SIZE);
	    memcpy(dist_policy->key, master_key, EVRB_KEY_SIZE);
	  }

	if(srtp_create(&loc->srtp_session, loc_policy))
		return -1;

	if(srtp_create(&dist->srtp_session, dist_policy))
		return -1;

	return 0;
}
Пример #23
0
Файл: rtp.c Проект: Geal/vlc
/**
 * Probes and initializes.
 */
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    int tp; /* transport protocol */

    if (!strcmp (demux->psz_access, "dccp"))
        tp = IPPROTO_DCCP;
    else
    if (!strcmp (demux->psz_access, "rtptcp"))
        tp = IPPROTO_TCP;
    else
    if (!strcmp (demux->psz_access, "rtp"))
        tp = IPPROTO_UDP;
    else
    if (!strcmp (demux->psz_access, "udplite"))
        tp = IPPROTO_UDPLITE;
    else
        return VLC_EGENERIC;

    char *tmp = strdup (demux->psz_location);
    if (tmp == NULL)
        return VLC_ENOMEM;

    char *shost;
    char *dhost = strchr (tmp, '@');
    if (dhost != NULL)
    {
        *(dhost++) = '\0';
        shost = tmp;
    }
    else
    {
        dhost = tmp;
        shost = NULL;
    }

    /* Parses the port numbers */
    int sport = 0, dport = 0;
    if (shost != NULL)
        sport = extract_port (&shost);
    if (dhost != NULL)
        dport = extract_port (&dhost);
    if (dport == 0)
        dport = 5004; /* avt-profile-1 port */

    int rtcp_dport = var_CreateGetInteger (obj, "rtcp-port");

    /* Try to connect */
    int fd = -1, rtcp_fd = -1;

    switch (tp)
    {
        case IPPROTO_UDP:
        case IPPROTO_UDPLITE:
            fd = net_OpenDgram (obj, dhost, dport, shost, sport, tp);
            if (fd == -1)
                break;
            if (rtcp_dport > 0) /* XXX: source port is unknown */
                rtcp_fd = net_OpenDgram (obj, dhost, rtcp_dport, shost, 0, tp);
            break;

         case IPPROTO_DCCP:
#ifndef SOCK_DCCP /* provisional API (FIXME) */
# ifdef __linux__
#  define SOCK_DCCP 6
# endif
#endif
#ifdef SOCK_DCCP
            var_Create (obj, "dccp-service", VLC_VAR_STRING);
            var_SetString (obj, "dccp-service", "RTPV"); /* FIXME: RTPA? */
            fd = net_Connect (obj, dhost, dport, SOCK_DCCP, tp);
#else
            msg_Err (obj, "DCCP support not included");
#endif
            break;

        case IPPROTO_TCP:
            fd = net_Connect (obj, dhost, dport, SOCK_STREAM, tp);
            break;
    }

    free (tmp);
    if (fd == -1)
        return VLC_EGENERIC;
    net_SetCSCov (fd, -1, 12);

    /* Initializes demux */
    demux_sys_t *p_sys = malloc (sizeof (*p_sys));
    if (p_sys == NULL)
    {
        net_Close (fd);
        if (rtcp_fd != -1)
            net_Close (rtcp_fd);
        return VLC_EGENERIC;
    }

    p_sys->chained_demux = NULL;
#ifdef HAVE_SRTP
    p_sys->srtp         = NULL;
#endif
    p_sys->fd           = fd;
    p_sys->rtcp_fd      = rtcp_fd;
    p_sys->max_src      = var_CreateGetInteger (obj, "rtp-max-src");
    p_sys->timeout      = var_CreateGetInteger (obj, "rtp-timeout")
                        * CLOCK_FREQ;
    p_sys->max_dropout  = var_CreateGetInteger (obj, "rtp-max-dropout");
    p_sys->max_misorder = var_CreateGetInteger (obj, "rtp-max-misorder");
    p_sys->thread_ready = false;
    p_sys->autodetect   = true;

    demux->pf_demux   = NULL;
    demux->pf_control = Control;
    demux->p_sys      = p_sys;

    p_sys->session = rtp_session_create (demux);
    if (p_sys->session == NULL)
        goto error;

#ifdef HAVE_SRTP
    char *key = var_CreateGetNonEmptyString (demux, "srtp-key");
    if (key)
    {
        vlc_gcrypt_init ();
        p_sys->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10,
                                   SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
        if (p_sys->srtp == NULL)
        {
            free (key);
            goto error;
        }

        char *salt = var_CreateGetNonEmptyString (demux, "srtp-salt");
        int val = srtp_setkeystring (p_sys->srtp, key, salt ? salt : "");
        free (salt);
        free (key);
        if (val)
        {
            msg_Err (obj, "bad SRTP key/salt combination (%s)",
                     vlc_strerror_c(val));
            goto error;
        }
    }
#endif

    if (vlc_clone (&p_sys->thread,
                   (tp != IPPROTO_TCP) ? rtp_dgram_thread : rtp_stream_thread,
                   demux, VLC_THREAD_PRIORITY_INPUT))
        goto error;
    p_sys->thread_ready = true;
    return VLC_SUCCESS;

error:
    Close (obj);
    return VLC_EGENERIC;
}
Пример #24
0
/*
 * Initialize and start SRTP session with the given parameters.
 */
PJ_DEF(pj_status_t) pjmedia_transport_srtp_start(
			   pjmedia_transport *tp,
			   const pjmedia_srtp_crypto *tx,
			   const pjmedia_srtp_crypto *rx)
{
    transport_srtp  *srtp = (transport_srtp*) tp;
    srtp_policy_t    tx_;
    srtp_policy_t    rx_;
    err_status_t     err;
    int		     cr_tx_idx = 0;
    int		     au_tx_idx = 0;
    int		     cr_rx_idx = 0;
    int		     au_rx_idx = 0;
    pj_status_t	     status = PJ_SUCCESS;

    PJ_ASSERT_RETURN(tp && tx && rx, PJ_EINVAL);

    pj_lock_acquire(srtp->mutex);

    if (srtp->session_inited) {
	pjmedia_transport_srtp_stop(tp);
    }

    /* Get encryption and authentication method */
    cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name);
    if (tx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
	cr_tx_idx = 0;
    if (tx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
	au_tx_idx = 0;

    cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name);
    if (rx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
	cr_rx_idx = 0;
    if (rx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
	au_rx_idx = 0;

    /* Check whether the crypto-suite requested is supported */
    if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 ||
	au_rx_idx == -1)
    {
	status = PJMEDIA_SRTP_ENOTSUPCRYPTO;
	goto on_return;
    }

    /* If all options points to 'NULL' method, just bypass SRTP */
    if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) {
	srtp->bypass_srtp = PJ_TRUE;
	goto on_return;
    }

    /* Check key length */
    if (tx->key.slen != (pj_ssize_t)crypto_suites[cr_tx_idx].cipher_key_len ||
        rx->key.slen != (pj_ssize_t)crypto_suites[cr_rx_idx].cipher_key_len)
    {
	status = PJMEDIA_SRTP_EINKEYLEN;
	goto on_return;
    }

    /* Init transmit direction */
    pj_bzero(&tx_, sizeof(srtp_policy_t));
    pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen);
    if (cr_tx_idx && au_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_conf_and_auth;
    else if (cr_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_conf;
    else if (au_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_auth;
    else
	tx_.rtp.sec_serv    = sec_serv_none;
    tx_.key		    = (uint8_t*)srtp->tx_key;
    tx_.ssrc.type	    = ssrc_any_outbound;
    tx_.ssrc.value	    = 0;
    tx_.rtp.cipher_type	    = crypto_suites[cr_tx_idx].cipher_type;
    tx_.rtp.cipher_key_len  = crypto_suites[cr_tx_idx].cipher_key_len;
    tx_.rtp.auth_type	    = crypto_suites[au_tx_idx].auth_type;
    tx_.rtp.auth_key_len    = crypto_suites[au_tx_idx].auth_key_len;
    tx_.rtp.auth_tag_len    = crypto_suites[au_tx_idx].srtp_auth_tag_len;
    tx_.rtcp		    = tx_.rtp;
    tx_.rtcp.auth_tag_len   = crypto_suites[au_tx_idx].srtcp_auth_tag_len;
    tx_.next		    = NULL;
    err = srtp_create(&srtp->srtp_tx_ctx, &tx_);
    if (err != err_status_ok) {
	status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
	goto on_return;
    }
    srtp->tx_policy = *tx;
    pj_strset(&srtp->tx_policy.key,  srtp->tx_key, tx->key.slen);
    srtp->tx_policy.name=pj_str(crypto_suites[get_crypto_idx(&tx->name)].name);


    /* Init receive direction */
    pj_bzero(&rx_, sizeof(srtp_policy_t));
    pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen);
    if (cr_rx_idx && au_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_conf_and_auth;
    else if (cr_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_conf;
    else if (au_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_auth;
    else
	rx_.rtp.sec_serv    = sec_serv_none;
    rx_.key		    = (uint8_t*)srtp->rx_key;
    rx_.ssrc.type	    = ssrc_any_inbound;
    rx_.ssrc.value	    = 0;
    rx_.rtp.sec_serv	    = crypto_suites[cr_rx_idx].service;
    rx_.rtp.cipher_type	    = crypto_suites[cr_rx_idx].cipher_type;
    rx_.rtp.cipher_key_len  = crypto_suites[cr_rx_idx].cipher_key_len;
    rx_.rtp.auth_type	    = crypto_suites[au_rx_idx].auth_type;
    rx_.rtp.auth_key_len    = crypto_suites[au_rx_idx].auth_key_len;
    rx_.rtp.auth_tag_len    = crypto_suites[au_rx_idx].srtp_auth_tag_len;
    rx_.rtcp		    = rx_.rtp;
    rx_.rtcp.auth_tag_len   = crypto_suites[au_rx_idx].srtcp_auth_tag_len;
    rx_.next		    = NULL;
    err = srtp_create(&srtp->srtp_rx_ctx, &rx_);
    if (err != err_status_ok) {
	srtp_dealloc(srtp->srtp_tx_ctx);
	status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
	goto on_return;
    }
    srtp->rx_policy = *rx;
    pj_strset(&srtp->rx_policy.key,  srtp->rx_key, rx->key.slen);
    srtp->rx_policy.name=pj_str(crypto_suites[get_crypto_idx(&rx->name)].name);

    /* Declare SRTP session initialized */
    srtp->session_inited = PJ_TRUE;

    /* Logging stuffs */
#if PJ_LOG_MAX_LEVEL >= 5
    {
	char b64[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)];
	int b64_len;

	/* TX crypto and key */
	b64_len = sizeof(b64);
	status = pj_base64_encode((pj_uint8_t*)tx->key.ptr, tx->key.slen,
				  b64, &b64_len);
	if (status != PJ_SUCCESS)
	    b64_len = pj_ansi_sprintf(b64, "--key too long--");
	else
	    b64[b64_len] = '\0';

	PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s",
		   srtp->tx_policy.name.ptr, b64));
	if (srtp->tx_policy.flags) {
	    PJ_LOG(5,(srtp->pool->obj_name, "TX: disable%s%s",
		      (cr_tx_idx?"":" enc"),
		      (au_tx_idx?"":" auth")));
	}

	/* RX crypto and key */
	b64_len = sizeof(b64);
	status = pj_base64_encode((pj_uint8_t*)rx->key.ptr, rx->key.slen,
				  b64, &b64_len);
	if (status != PJ_SUCCESS)
	    b64_len = pj_ansi_sprintf(b64, "--key too long--");
	else
	    b64[b64_len] = '\0';

	PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s",
		   srtp->rx_policy.name.ptr, b64));
	if (srtp->rx_policy.flags) {
	    PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s",
		      (cr_rx_idx?"":" enc"),
		      (au_rx_idx?"":" auth")));
	}
    }
#endif

on_return:
    pj_lock_release(srtp->mutex);
    return status;
}
Пример #25
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;
}
Пример #26
0
int
rtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy) {
    return srtp_create(&sender->srtp_ctx, policy);
}
Пример #27
0
err_status_t ortp_srtp_create(srtp_t *session, const srtp_policy_t *policy)
{
	int i;
	i = srtp_create(session, policy);
	return i;
}
Пример #28
0
srtp_err_status_t
rtp_decoder_init_srtp(rtp_decoder_t decoder, unsigned int ssrc) {
  decoder->policy.ssrc.value = htonl(ssrc);
  return srtp_create(&decoder->srtp_ctx, &decoder->policy);
}
Пример #29
0
/*
 * Initialize and start SRTP session with the given parameters.
 */
PJ_DEF(pj_status_t) pjmedia_transport_srtp_start(
			   pjmedia_transport *tp, 
			   const pjmedia_srtp_crypto *tx,
			   const pjmedia_srtp_crypto *rx)
{
    transport_srtp  *srtp = (transport_srtp*) tp;
    srtp_policy_t    tx_;
    srtp_policy_t    rx_;
    err_status_t     err;
    int		     cr_tx_idx = 0;
    int		     au_tx_idx = 0;
    int		     cr_rx_idx = 0;
    int		     au_rx_idx = 0;
    int		     crypto_suites_cnt;

    PJ_ASSERT_RETURN(tp && tx && rx, PJ_EINVAL);

    if (srtp->session_inited) {
	pjmedia_transport_srtp_stop(tp);
    }

    crypto_suites_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);

    /* Get encryption and authentication method */
    cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name);
    if (tx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
	cr_tx_idx = 0;
    if (tx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
	au_tx_idx = 0;

    cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name);
    if (rx->flags & PJMEDIA_SRTP_NO_ENCRYPTION)
	cr_rx_idx = 0;
    if (rx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION)
	au_rx_idx = 0;

    /* Check whether the crypto-suite requested is supported */
    if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || 
	au_rx_idx == -1)
	return PJMEDIA_SRTP_ENOTSUPCRYPTO;

    /* If all options points to 'NULL' method, just bypass SRTP */
    if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) {
	srtp->bypass_srtp = PJ_TRUE;
	return PJ_SUCCESS;
    }

    /* Check key length */
    if (tx->key.slen != (pj_ssize_t)crypto_suites[cr_tx_idx].cipher_key_len ||
        rx->key.slen != (pj_ssize_t)crypto_suites[cr_rx_idx].cipher_key_len)
	return PJMEDIA_SRTP_EINKEYLEN;

    /* Init transmit direction */
    pj_bzero(&tx_, sizeof(srtp_policy_t));
    pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen);
    if (cr_tx_idx && au_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_conf_and_auth;
    else if (cr_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_conf;
    else if (au_tx_idx)
	tx_.rtp.sec_serv    = sec_serv_auth;
    else
	tx_.rtp.sec_serv    = sec_serv_none;
    tx_.key		    = (uint8_t*)srtp->tx_key;
    tx_.ssrc.type	    = ssrc_any_outbound;
    tx_.ssrc.value	    = 0;
    tx_.rtp.cipher_type	    = crypto_suites[cr_tx_idx].cipher_type;
    tx_.rtp.cipher_key_len  = crypto_suites[cr_tx_idx].cipher_key_len;
    tx_.rtp.auth_type	    = crypto_suites[au_tx_idx].auth_type;
    tx_.rtp.auth_key_len    = crypto_suites[au_tx_idx].auth_key_len;
    tx_.rtp.auth_tag_len    = crypto_suites[au_tx_idx].srtp_auth_tag_len;
    tx_.rtcp		    = tx_.rtp;
    tx_.rtcp.auth_tag_len   = crypto_suites[au_tx_idx].srtcp_auth_tag_len;
    tx_.next		    = NULL;
    err = srtp_create(&srtp->srtp_tx_ctx, &tx_);
    if (err != err_status_ok) {
	return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
    }
    srtp->tx_policy = *tx;
    pj_strset(&srtp->tx_policy.key,  srtp->tx_key, tx->key.slen);
    srtp->tx_policy.name=pj_str(crypto_suites[get_crypto_idx(&tx->name)].name);


    /* Init receive direction */
    pj_bzero(&rx_, sizeof(srtp_policy_t));
    pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen);
    if (cr_rx_idx && au_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_conf_and_auth;
    else if (cr_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_conf;
    else if (au_rx_idx)
	rx_.rtp.sec_serv    = sec_serv_auth;
    else
	rx_.rtp.sec_serv    = sec_serv_none;
    rx_.key		    = (uint8_t*)srtp->rx_key;
    rx_.ssrc.type	    = ssrc_any_inbound;
    rx_.ssrc.value	    = 0;
    rx_.rtp.sec_serv	    = crypto_suites[cr_rx_idx].service;
    rx_.rtp.cipher_type	    = crypto_suites[cr_rx_idx].cipher_type;
    rx_.rtp.cipher_key_len  = crypto_suites[cr_rx_idx].cipher_key_len;
    rx_.rtp.auth_type	    = crypto_suites[au_rx_idx].auth_type;
    rx_.rtp.auth_key_len    = crypto_suites[au_rx_idx].auth_key_len;
    rx_.rtp.auth_tag_len    = crypto_suites[au_rx_idx].srtp_auth_tag_len;
    rx_.rtcp		    = rx_.rtp;
    rx_.rtcp.auth_tag_len   = crypto_suites[au_rx_idx].srtcp_auth_tag_len;
    rx_.next		    = NULL;
    err = srtp_create(&srtp->srtp_rx_ctx, &rx_);
    if (err != err_status_ok) {
	srtp_dealloc(srtp->srtp_tx_ctx);
	return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
    }
    srtp->rx_policy = *rx;
    pj_strset(&srtp->rx_policy.key,  srtp->rx_key, rx->key.slen);
    srtp->rx_policy.name=pj_str(crypto_suites[get_crypto_idx(&rx->name)].name);

    /* Declare SRTP session initialized */
    srtp->session_inited = PJ_TRUE;

    PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s", srtp->tx_policy.name.ptr,
	       octet_string_hex_string(tx->key.ptr, tx->key.slen)));
    if (srtp->tx_policy.flags) {
	PJ_LOG(5,(srtp->pool->obj_name,"TX: disable%s%s", (cr_tx_idx?"":" enc"),
		  (au_tx_idx?"":" auth")));
    }

    PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s", srtp->rx_policy.name.ptr,
	       octet_string_hex_string(rx->key.ptr, rx->key.slen)));
    if (srtp->rx_policy.flags) {
	PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s", (cr_rx_idx?"":" enc"),
		  (au_rx_idx?"":" auth")));
    }

    return PJ_SUCCESS;
}
Пример #30
0
void janus_dtls_srtp_incoming_msg(janus_dtls_srtp *dtls, char *buf, uint16_t len) {
	if(dtls == NULL) {
		JANUS_LOG(LOG_ERR, "No DTLS-SRTP stack, no incoming message...\n");
		return;
	}
	janus_ice_component *component = (janus_ice_component *)dtls->component;
	if(component == NULL) {
		JANUS_LOG(LOG_ERR, "No component, no DTLS...\n");
		return;
	}
	janus_ice_stream *stream = component->stream;
	if(!stream) {
		JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n");
		return;
	}
	janus_ice_handle *handle = stream->handle;
	if(!handle || !handle->agent) {
		JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n");
		return;
	}
	if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT)) {
		JANUS_LOG(LOG_ERR, "Alert already received, clearing up...\n");
		return;
	}
	if(!dtls->ssl || !dtls->read_bio) {
		JANUS_LOG(LOG_ERR, "[%"SCNu64"] No DTLS stuff for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
		return;
	}
	/* We just got a message, can we get rid of the last sent message? */
	if(dtls->dtls_last_msg != NULL) {
		g_free(dtls->dtls_last_msg);
		dtls->dtls_last_msg = NULL;
		dtls->dtls_last_len = 0;
	}
	janus_dtls_fd_bridge(dtls);
	int written = BIO_write(dtls->read_bio, buf, len);
	JANUS_LOG(LOG_HUGE, "    Written %d of those bytes on the read BIO...\n", written);
	janus_dtls_fd_bridge(dtls);
	int read = SSL_read(dtls->ssl, buf, len);
	JANUS_LOG(LOG_HUGE, "    ...and read %d of them from SSL...\n", read);
	janus_dtls_fd_bridge(dtls);
	if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_STOP) || janus_is_stopping()) {
		/* DTLS alert received, we should end it here */
		JANUS_LOG(LOG_VERB, "[%"SCNu64"] Forced to stop it here...\n", handle->handle_id);
		return;
	}
	if(SSL_is_init_finished(dtls->ssl)) {
		JANUS_LOG(LOG_VERB, "[%"SCNu64"] DTLS established, yay!\n", handle->handle_id);
		/* Check the remote fingerprint */
		X509 *rcert = SSL_get_peer_certificate(dtls->ssl);
		if(!rcert) {
			JANUS_LOG(LOG_ERR, "[%"SCNu64"] No remote certificate??\n", handle->handle_id);
		} else {
			unsigned int rsize;
			unsigned char rfingerprint[EVP_MAX_MD_SIZE];
			char remote_fingerprint[160];
			char *rfp = (char *)&remote_fingerprint;
			if(handle->remote_hashing && !strcasecmp(handle->remote_hashing, "sha-1")) {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-1 fingerprint of remote certificate...\n", handle->handle_id);
				X509_digest(rcert, EVP_sha1(), (unsigned char *)rfingerprint, &rsize);
			} else {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-256 fingerprint of remote certificate...\n", handle->handle_id);
				X509_digest(rcert, EVP_sha256(), (unsigned char *)rfingerprint, &rsize);
			}
			X509_free(rcert);
			rcert = NULL;
			int i = 0;
			for(i = 0; i < rsize; i++) {
				sprintf(rfp, "%.2X:", rfingerprint[i]);
				rfp += 3;
			}
			*(rfp-1) = 0;
			JANUS_LOG(LOG_VERB, "[%"SCNu64"] Remote fingerprint (%s) of the client is %s\n",
				handle->handle_id, handle->remote_hashing ? handle->remote_hashing : "sha-256", remote_fingerprint);
			if(!strcasecmp(remote_fingerprint, handle->remote_fingerprint ? handle->remote_fingerprint : "(none)")) {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"]  Fingerprint is a match!\n", handle->handle_id);
				dtls->dtls_state = JANUS_DTLS_STATE_CONNECTED;
			} else {
				/* FIXME NOT a match! MITM? */
				JANUS_LOG(LOG_ERR, "[%"SCNu64"]  Fingerprint is NOT a match! expected %s\n", handle->handle_id, handle->remote_fingerprint);
				dtls->dtls_state = JANUS_DTLS_STATE_FAILED;
				goto done;
			}
			if(dtls->dtls_state == JANUS_DTLS_STATE_CONNECTED) {
				/* Complete with SRTP setup */
				unsigned char material[SRTP_MASTER_LENGTH*2];
				unsigned char *local_key, *local_salt, *remote_key, *remote_salt;
				/* Export keying material for SRTP */
				if (!SSL_export_keying_material(dtls->ssl, material, SRTP_MASTER_LENGTH*2, "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) {
					/* Oops... */
					JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, couldn't extract SRTP keying material for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
					goto done;
				}
				/* Key derivation (http://tools.ietf.org/html/rfc5764#section-4.2) */
				if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) {
					local_key = material;
					remote_key = local_key + SRTP_MASTER_KEY_LENGTH;
					local_salt = remote_key + SRTP_MASTER_KEY_LENGTH;
					remote_salt = local_salt + SRTP_MASTER_SALT_LENGTH;
				} else {
					remote_key = material;
					local_key = remote_key + SRTP_MASTER_KEY_LENGTH;
					remote_salt = local_key + SRTP_MASTER_KEY_LENGTH;
					local_salt = remote_salt + SRTP_MASTER_SALT_LENGTH;
				}
				/* Build master keys and set SRTP policies */
					/* Remote (inbound) */
				crypto_policy_set_rtp_default(&(dtls->remote_policy.rtp));
				crypto_policy_set_rtcp_default(&(dtls->remote_policy.rtcp));
				dtls->remote_policy.ssrc.type = ssrc_any_inbound;
				dtls->remote_policy.key = calloc(SRTP_MASTER_LENGTH+8, sizeof(char));
				if(dtls->remote_policy.key == NULL) {
					JANUS_LOG(LOG_FATAL, "Memory error!\n");
					goto done;
				}
				memcpy(dtls->remote_policy.key, remote_key, SRTP_MASTER_KEY_LENGTH);
				memcpy(dtls->remote_policy.key + SRTP_MASTER_KEY_LENGTH, remote_salt, SRTP_MASTER_SALT_LENGTH);
				dtls->remote_policy.window_size = 128;
				dtls->remote_policy.allow_repeat_tx = 0;
				dtls->remote_policy.next = NULL;
					/* Local (outbound) */
				crypto_policy_set_rtp_default(&(dtls->local_policy.rtp));
				crypto_policy_set_rtcp_default(&(dtls->local_policy.rtcp));
				dtls->local_policy.ssrc.type = ssrc_any_outbound;
				dtls->local_policy.key = calloc(SRTP_MASTER_LENGTH+8, sizeof(char));
				if(dtls->local_policy.key == NULL) {
					JANUS_LOG(LOG_FATAL, "Memory error!\n");
					goto done;
				}
				memcpy(dtls->local_policy.key, local_key, SRTP_MASTER_KEY_LENGTH);
				memcpy(dtls->local_policy.key + SRTP_MASTER_KEY_LENGTH, local_salt, SRTP_MASTER_SALT_LENGTH);
				dtls->local_policy.window_size = 128;
				dtls->local_policy.allow_repeat_tx = 0;
				dtls->local_policy.next = NULL;
				/* Create SRTP sessions */
				err_status_t res = srtp_create(&(dtls->srtp_in), &(dtls->remote_policy));
				if(res != err_status_ok) {
					/* Something went wrong... */
					JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating inbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
					JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_get_srtp_error(res));
					goto done;
				}
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created inbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
				res = srtp_create(&(dtls->srtp_out), &(dtls->local_policy));
				if(res != err_status_ok) {
					/* Something went wrong... */
					JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating outbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
					JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_get_srtp_error(res));
					goto done;
				}
				dtls->srtp_valid = 1;
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created outbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
			}
done:
			if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT) && dtls->srtp_valid) {
				/* Handshake successfully completed */
				janus_ice_dtls_handshake_done(handle, component);
			} else {
				/* Something went wrong in either DTLS or SRTP... tell the plugin about it */
				janus_dtls_callback(dtls->ssl, SSL_CB_ALERT, 0);
			}
		}
	}
}