Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 303637) +++ channels/chan_sip.c (working copy) @@ -1541,7 +1541,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno); /*------ SRTP Support -------- */ -static int setup_srtp(struct sip_srtp **srtp); +static int setup_srtp(struct sip_srtp **srtp, int suite); static int process_crypto(struct sip_pvt *p, struct ast_rtp_instance *rtp, struct sip_srtp **srtp, const char *a); /*------ T38 Support --------- */ @@ -5203,22 +5203,28 @@ } if (ast_test_flag(&p->flags[1], SIP_PAGE2_USE_SRTP)) { + unsigned int suite; + + suite = (ast_test_flag(&p->flags[1], SIP_PAGE2_USE_SRTP) >> 28); + ast_verbose(VERBOSE_PREFIX_2 "Encrypted Media is required, offering suite %d (%s).\n", + suite, suite2desc(suite)); + if (ast_test_flag(&p->flags[0], SIP_REINVITE)) { ast_debug(1, "Direct media not possible when using SRTP, ignoring canreinvite setting\n"); ast_clear_flag(&p->flags[0], SIP_REINVITE); } - if (p->rtp && !p->srtp && setup_srtp(&p->srtp) < 0) { + if (p->rtp && !p->srtp && setup_srtp(&p->srtp, suite) < 0) { ast_log(LOG_WARNING, "SRTP audio setup failed\n"); return -1; } - if (p->vrtp && !p->vsrtp && setup_srtp(&p->vsrtp) < 0) { + if (p->vrtp && !p->vsrtp && setup_srtp(&p->vsrtp, suite) < 0) { ast_log(LOG_WARNING, "SRTP video setup failed\n"); return -1; } - if (p->trtp && !p->vsrtp && setup_srtp(&p->tsrtp) < 0) { + if (p->trtp && !p->vsrtp && setup_srtp(&p->tsrtp, suite) < 0) { ast_log(LOG_WARNING, "SRTP text setup failed\n"); return -1; } @@ -10578,9 +10584,14 @@ if (!srtp->crypto) { srtp->crypto = sdp_crypto_setup(); } - if (srtp->crypto && (sdp_crypto_offer(srtp->crypto) >= 0)) { + if (srtp->crypto) { + int res; + + res = sdp_crypto_offer(srtp->crypto, ast_test_flag(srtp, SRTP_CRYPTO_SUITE) >> 4); + if (res >= 0) { *a_crypto = sdp_crypto_attrib(srtp->crypto); } + } if (!*a_crypto) { ast_log(LOG_WARNING, "No SRTP key management enabled\n"); @@ -26391,7 +26402,26 @@ } else if (!strcasecmp(v->name, "use_q850_reason")) { ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_Q850_REASON); } else if (!strcasecmp(v->name, "encryption")) { - ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP); + ast_verbose(VERBOSE_PREFIX_2 "from sip.conf: encryption=%s.\n", v->value); + ast_clear_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_AES_80); + ast_clear_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_AES_32); + ast_clear_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_F8_80); + ast_clear_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_NULL); + if ((!strcasecmp(v->value, "yes")) || (!strcasecmp(v->value, "aes_80"))) { + ast_set_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_AES_80); + } else if (!strcasecmp(v->value, "aes_32")) { + ast_set_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_AES_32); + } else if (!strcasecmp(v->value, "f8_80")) { + /* ast_set_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_F8_80); */ + ast_log(LOG_WARNING, "Unsupported crypto suite: %s, please use aes_80 or aes_32.\n", v->value); + } else if (!strcasecmp(v->value, "null")) { + /* ast_set_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP_NULL); */ + ast_log(LOG_WARNING, "Unsupported crypto suite: %s, please use aes_80 or aes_32.\n", v->value); + } else { + if (strcasecmp(v->value, "no")) { + ast_log(LOG_WARNING, "Invalid crypto suite: %s, please use aes_80 or aes_32.\n", v->value); + } + } } else if (!strcasecmp(v->name, "snom_aoc_enabled")) { ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC); } @@ -28210,8 +28240,21 @@ } /* SRTP */ -static int setup_srtp(struct sip_srtp **srtp) +static void set_srtp_suite_flags(struct sip_srtp *srtp, int suite) { + ast_clear_flag(srtp, SRTP_CRYPTO_SUITE_USE_AES_80); + ast_clear_flag(srtp, SRTP_CRYPTO_SUITE_USE_AES_32); + ast_clear_flag(srtp, SRTP_CRYPTO_SUITE_USE_F8_80); + ast_clear_flag(srtp, SRTP_CRYPTO_SUITE_USE_NULL); + if (suite <= 15 && suite >= 0) { + ast_set_flag(srtp, suite << 4); + } + ast_verbose(VERBOSE_PREFIX_2 "SRTP_CRYPTO_SUITE is set to %d (%s).\n", + ast_test_flag(srtp, SRTP_CRYPTO_SUITE), suite2desc(suite)); +} + +static int setup_srtp(struct sip_srtp **srtp, int suite) +{ if (!ast_rtp_engine_srtp_is_registered()) { ast_log(LOG_ERROR, "No SRTP module loaded, can't setup SRTP session.\n"); return -1; @@ -28221,11 +28264,15 @@ return -1; } + set_srtp_suite_flags(*srtp, suite); + return 0; } static int process_crypto(struct sip_pvt *p, struct ast_rtp_instance *rtp, struct sip_srtp **srtp, const char *a) { + int suite; + if (strncasecmp(a, "crypto:", 7)) { return FALSE; } @@ -28235,7 +28282,7 @@ return FALSE; } - if (setup_srtp(srtp) < 0) { + if (setup_srtp(srtp, 0) < 0) { return FALSE; } } @@ -28250,9 +28297,11 @@ return FALSE; } - if (sdp_crypto_process((*srtp)->crypto, a, rtp) < 0) { + suite = sdp_crypto_process((*srtp)->crypto, a, rtp); + if (suite < 0) { return FALSE; } + set_srtp_suite_flags(*srtp, suite); ast_set_flag(*srtp, SRTP_CRYPTO_OFFER_OK); Index: channels/sip/include/sip.h =================================================================== --- channels/sip/include/sip.h (revision 303637) +++ channels/sip/include/sip.h (working copy) @@ -335,7 +335,11 @@ #define SIP_PAGE2_UDPTL_DESTINATION (1 << 25) /*!< DP: Use source IP of RTP as destination if NAT is enabled */ #define SIP_PAGE2_VIDEOSUPPORT_ALWAYS (1 << 26) /*!< DP: Always set up video, even if endpoints don't support it */ #define SIP_PAGE2_HAVEPEERCONTEXT (1 << 27) /*< Are we associated with a configured peer context? */ -#define SIP_PAGE2_USE_SRTP (1 << 28) /*!< DP: Whether we should offer (only) SRTP */ +#define SIP_PAGE2_USE_SRTP (15 << 28) /*!< DP: Whether we should offer (only) SRTP */ +#define SIP_PAGE2_USE_SRTP_AES_80 (1 << 28) /*!< DP: SRTP suite to offer */ +#define SIP_PAGE2_USE_SRTP_AES_32 (2 << 28) /*!< DP: SRTP suite to offer */ +#define SIP_PAGE2_USE_SRTP_F8_80 (4 << 28) /*!< DP: SRTP suite to offer */ +#define SIP_PAGE2_USE_SRTP_NULL (8 << 28) /*!< DP: SRTP suite to offer */ #define SIP_PAGE2_FLAGS_TO_COPY \ (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_IGNORESDPVERSION | \ Index: channels/sip/include/sdp_crypto.h =================================================================== --- channels/sip/include/sdp_crypto.h (revision 303637) +++ channels/sip/include/sdp_crypto.h (working copy) @@ -32,6 +32,21 @@ struct sdp_crypto; +struct suite2stringtable { + const int suite; + const char *desc; +}; +/*! \brief Return the description for a suite value + * + * \details + * This function looks in suite2stringtable using suite value as index + * + * \param suite A valid sdp_crypto suite value + * + * \retval a pointer to a suite description + */ +const char * suite2desc(int suite); + /*! \brief Initialize an return an sdp_crypto struct * * \details @@ -52,8 +67,8 @@ * \param attr the a:crypto line from SDP * \param rtp The rtp instance associated with the SDP being parsed * - * \retval 0 success - * \retval nonzero failure + * \retval suite_val (enum ast_srtp_suite) success + * \retval -1 failure */ int sdp_crypto_process(struct sdp_crypto *p, const char *attr, struct ast_rtp_instance *rtp); @@ -64,11 +79,12 @@ * The offer is stored on the sdp_crypto struct in a_crypto * * \param A valid sdp_crypto struct + * \param A valid sdp_crypto suite value * * \retval 0 success * \retval nonzero failure */ -int sdp_crypto_offer(struct sdp_crypto *p); +int sdp_crypto_offer(struct sdp_crypto *p, enum ast_srtp_suite suite); /*! \brief Return the a_crypto value of the sdp_crypto struct Index: channels/sip/include/srtp.h =================================================================== --- channels/sip/include/srtp.h (revision 303637) +++ channels/sip/include/srtp.h (working copy) @@ -34,6 +34,11 @@ #define SRTP_ENCR_OPTIONAL (1 << 1) /* SRTP encryption optional */ #define SRTP_CRYPTO_ENABLE (1 << 2) #define SRTP_CRYPTO_OFFER_OK (1 << 3) +#define SRTP_CRYPTO_SUITE (15 << 4) /* Preferred SRTP encryption suite */ +#define SRTP_CRYPTO_SUITE_USE_AES_80 (1 << 4) +#define SRTP_CRYPTO_SUITE_USE_AES_32 (2 << 4) +#define SRTP_CRYPTO_SUITE_USE_F8_80 (4 << 4) +#define SRTP_CRYPTO_SUITE_USE_NULL (8 << 4) /*! \brief structure for secure RTP audio */ struct sip_srtp { Index: channels/sip/sdp_crypto.c =================================================================== --- channels/sip/sdp_crypto.c (revision 303637) +++ channels/sip/sdp_crypto.c (working copy) @@ -47,6 +47,27 @@ char local_key64[SRTP_MASTER_LEN64]; }; +const struct suite2stringtable suite2string[] = { + { AST_AES_CM_128_HMAC_SHA1_80, "AES_CM_128_HMAC_SHA1_80" }, + { AST_AES_CM_128_HMAC_SHA1_32, "AES_CM_128_HMAC_SHA1_32" }, + { AST_F8_128_HMAC_SHA1_80, "F8_128_HMAC_SHA1_80" }, + { AST_NULL_CIPHER, "NULL_CIPHER" }, + { 999, "UNDEFINED" } +}; + +const char * suite2desc(int suite) +{ + int i = 0; + + while (suite2string[i].suite != 999) { + if (suite2string[i].suite == suite) { + return suite2string[i].desc; + } + i++; + } + return suite2string[999].desc; +} + static int set_crypto_policy(struct ast_srtp_policy *policy, int suite_val, const unsigned char *master_key, unsigned long ssrc, int inbound); static struct sdp_crypto *sdp_crypto_alloc(void) @@ -281,19 +302,20 @@ snprintf(p->a_crypto, attr_len + 10, "a=crypto:%s %s inline:%s\r\n", tag, suite, p->local_key64); } - return 0; + return suite_val; } -int sdp_crypto_offer(struct sdp_crypto *p) +int sdp_crypto_offer(struct sdp_crypto *p, enum ast_srtp_suite suite) { char crypto_buf[128]; - const char *crypto_suite = "AES_CM_128_HMAC_SHA1_80"; /* Crypto offer */ if (p->a_crypto) { ast_free(p->a_crypto); } - if (snprintf(crypto_buf, sizeof(crypto_buf), "a=crypto:1 %s inline:%s\r\n", crypto_suite, p->local_key64) < 1) { + ast_verbose(VERBOSE_PREFIX_2 "Selecting %d (%s) for srtp crypto offer.\n", suite, suite2desc(suite)); + if (snprintf(crypto_buf, sizeof(crypto_buf), "a=crypto:1 %s inline:%s\r\n", + suite2desc(suite), p->local_key64) < 1) { return -1; } Index: include/asterisk/res_srtp.h =================================================================== --- include/asterisk/res_srtp.h (revision 303637) +++ include/asterisk/res_srtp.h (working copy) @@ -44,7 +44,8 @@ enum ast_srtp_suite { AST_AES_CM_128_HMAC_SHA1_80 = 1, AST_AES_CM_128_HMAC_SHA1_32 = 2, - AST_F8_128_HMAC_SHA1_80 = 3 + AST_F8_128_HMAC_SHA1_80 = 4, + AST_NULL_CIPHER = 8 }; struct ast_srtp_policy_res {