/** * @briefThis function is called by ZRTP engine as soon as SRTP secrets are ready to be used * Depending on which role we assume in the ZRTP protocol (Initiator or Responder, randomly selected) * both secrets may not be available at the same time, the part argument is either * ZRTP_SRTP_SECRETS_FOR_SENDER or ZRTP_SRTP_SECRETS_FOR_RECEIVER. * Secrets are used to set up SRTP sessions * * @param[in] clientData Pointer to our ZrtpContext structure used to retrieve stream sessions structure needed to setup SRTP sessions * @param[in] secrets The SRTP keys and algorithm setup * @param[in] part for receiver or for sender in order to determine which SRTP stream the secret apply to * @return 0 on success */ static int32_t ms_zrtp_srtpSecretsAvailable(void* clientData, bzrtpSrtpSecrets_t* secrets, uint8_t part) { MSZrtpContext *userData = (MSZrtpContext *)clientData; // Get authentication and cipher algorithms in srtp format if ((secrets->authTagAlgo != ZRTP_AUTHTAG_HS32) && ((secrets->authTagAlgo != ZRTP_AUTHTAG_HS80))) { ms_fatal("unsupported authentication algorithm by srtp"); } if ((secrets->cipherAlgo != ZRTP_CIPHER_AES1) && (secrets->cipherAlgo != ZRTP_CIPHER_AES3)) { ms_fatal("unsupported cipher algorithm by srtp"); } ms_message("ZRTP secrets are ready for %s; auth tag algo is %s and cipher algo is %s", (part==ZRTP_SRTP_SECRETS_FOR_SENDER)?"sender":"receiver", (secrets->authTagAlgo==ZRTP_AUTHTAG_HS32)?"HS32":"HS80", (secrets->cipherAlgo==ZRTP_CIPHER_AES3)?"AES256":"AES128"); if (part==ZRTP_SRTP_SECRETS_FOR_RECEIVER) { uint8_t *key = (uint8_t *)ms_malloc0((secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength+16)*sizeof(uint8_t)); memcpy(key, secrets->peerSrtpKey, secrets->peerSrtpKeyLength); memcpy(key + secrets->peerSrtpKeyLength, secrets->peerSrtpSalt, secrets->peerSrtpSaltLength); if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS32){ if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){ ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_256_SHA1_32, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS); }else{ ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_128_SHA1_32, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS); } }else if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS80){ if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){ ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_256_SHA1_80, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS); }else{ ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS); } }else{ ms_fatal("unsupported auth tag"); } ms_free(key); } if (part==ZRTP_SRTP_SECRETS_FOR_SENDER) { uint8_t *key = (uint8_t *)ms_malloc0((secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength+16)*sizeof(uint8_t)); memcpy(key, secrets->selfSrtpKey, secrets->selfSrtpKeyLength); memcpy(key + secrets->selfSrtpKeyLength, secrets->selfSrtpSalt, secrets->selfSrtpSaltLength); if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS32){ if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){ ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_256_SHA1_32, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS); }else{ ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_128_SHA1_32, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS); } }else if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS80){ if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){ ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_256_SHA1_80, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS); }else{ ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS); } }else{ ms_fatal("unsupported auth tag"); } ms_free(key); } return 0; }
static int ms_dtls_srtp_rtcp_process_on_receive(struct _RtpTransportModifier *t, mblk_t *msg) { MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data; int ret; size_t msgLength = msgdsize(msg); // check incoming message length if (msgLength<RTP_FIXED_HEADER_SIZE) { return msgLength; } /* check if we have an on-going handshake */ if (ctx->rtp_channel_status == DTLS_STATUS_CONTEXT_NOT_READY) { return msgLength; } /* check if it is a DTLS packet and process it */ if (ms_dtls_srtp_process_dtls_packet(msg, ctx, &ret, FALSE) == TRUE){ if ((ret==0) && (ctx->rtcp_channel_status == DTLS_STATUS_CONTEXT_READY)) { /* rtcp handshake is over, give the keys to srtp : 128 bits client write - 128 bits server write - 112 bits client salt - 112 server salt */ uint8_t *key = (uint8_t *)ms_malloc0(256); MSCryptoSuite agreed_srtp_protection_profile = MS_CRYPTO_SUITE_INVALID; ctx->rtcp_channel_status = DTLS_STATUS_HANDSHAKE_OVER; /* check the srtp profile get selected during handshake */ agreed_srtp_protection_profile = ms_polarssl_dtls_srtp_protection_profile_to_ms_crypto_suite(ssl_get_dtls_srtp_protection_profile(&(ctx->rtcp_dtls_context->ssl))); if ( agreed_srtp_protection_profile == MS_CRYPTO_SUITE_INVALID) { ms_error("DTLS RTCP Handshake successful but unable to agree on srtp_profile to use"); } else { if (ms_dtls_srtp_check_certificate_fingerprint(ssl_get_peer_cert(&(ctx->rtcp_dtls_context->ssl)), (const char *)(ctx->peer_fingerprint)) == 1) { ms_message("DTLS RTCP Handshake successful and fingerprints match, srtp protection profile %d", ctx->rtcp_dtls_context->ssl.chosen_dtls_srtp_profile); ctx->rtcp_time_reference = 0; /* unarm the timer */ if (ctx->role == MSDtlsSrtpRoleIsServer) { /* reception(client write) key and salt +16bits padding */ memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys, DTLS_SRTP_KEY_LEN); memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN); ms_media_stream_sessions_set_srtp_recv_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM); /* emission(server write) key and salt +16bits padding */ memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN); memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN); ms_media_stream_sessions_set_srtp_send_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM); } else if (ctx->role == MSDtlsSrtpRoleIsClient){ /* this enpoint act as DTLS client */ /* emission(client write) key and salt +16bits padding */ memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys, DTLS_SRTP_KEY_LEN); memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN); ms_media_stream_sessions_set_srtp_send_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM); /* reception(server write) key and salt +16bits padding */ memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN); memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN); ms_media_stream_sessions_set_srtp_recv_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM); } ms_free(key); ms_dtls_srtp_check_channels_status(ctx); } } ret = ssl_close_notify( &(ctx->rtcp_dtls_context->ssl) ); } return 0; } return msgdsize(msg); }