OpalRTPSession::SendReceiveStatus OpalDTLSSRTPSession::ExecuteHandshake(Channel channel) { { PWaitAndSignal mutex(m_dataMutex); if (m_remotePort[channel] == 0) return e_IgnorePacket; // Too early if (m_sslChannel[channel] == NULL) return e_ProcessPacket; // Too late (done) } SSLChannel & sslChannel = *m_sslChannel[channel]; if (!sslChannel.ExecuteHandshake()) return e_AbortTransport; const OpalMediaCryptoSuite* cryptoSuite = NULL; srtp_profile_t profile = srtp_profile_reserved; for (PINDEX i = 0; i < PARRAYSIZE(ProfileNames); ++i) { if (sslChannel.GetSelectedProfile() == ProfileNames[i].m_dtlsName) { profile = ProfileNames[i].m_profile; cryptoSuite = OpalMediaCryptoSuiteFactory::CreateInstance(ProfileNames[i].m_opalName); break; } } if (profile == srtp_profile_reserved || cryptoSuite == NULL) { PTRACE(2, "Error in SRTP profile."); return e_AbortTransport; } PINDEX masterKeyLength = srtp_profile_get_master_key_length(profile); PINDEX masterSaltLength = srtp_profile_get_master_salt_length(profile); PBYTEArray keyMaterial = sslChannel.GetKeyMaterial(((masterSaltLength + masterKeyLength) << 1), "EXTRACTOR-dtls_srtp"); if (keyMaterial.IsEmpty()) return e_AbortTransport; OpalSRTPKeyInfo * keyInfo = dynamic_cast<OpalSRTPKeyInfo*>(cryptoSuite->CreateKeyInfo()); PAssertNULL(keyInfo); keyInfo->SetCipherKey(PBYTEArray(keyMaterial, masterKeyLength)); keyInfo->SetAuthSalt(PBYTEArray(keyMaterial + masterKeyLength*2, masterSaltLength)); ApplyKeyToSRTP(*keyInfo, sslChannel.IsServer() ? e_Receiver : e_Sender); keyInfo->SetCipherKey(PBYTEArray(keyMaterial + masterKeyLength, masterKeyLength)); keyInfo->SetAuthSalt(PBYTEArray(keyMaterial + masterKeyLength*2 + masterSaltLength, masterSaltLength)); ApplyKeyToSRTP(*keyInfo, sslChannel.IsServer() ? e_Sender : e_Receiver); delete keyInfo; m_queueChannel[channel].Close(); sslChannel.Detach(PChannel::ShutdownWrite); // Do not close the socket! delete m_sslChannel[channel]; m_sslChannel[channel] = NULL; return e_ProcessPacket; }
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; }