Ignore:
Timestamp:
Jun 3, 2017 9:22:34 AM (7 years ago)
Author:
nanang
Message:

Re #2018: Initial version of DTLS-SRTP implementation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/transport_srtp.c

    r5588 r5597  
    2222#include <pjmedia/endpoint.h> 
    2323#include <pjlib-util/base64.h> 
     24#include <pj/array.h> 
    2425#include <pj/assert.h> 
    2526#include <pj/ctype.h> 
     
    8081    char                *name; 
    8182    cipher_type_id_t     cipher_type; 
    82     unsigned             cipher_key_len; 
     83    unsigned             cipher_key_len;    /* key + salt length    */ 
     84    unsigned             cipher_salt_len;   /* salt only length     */ 
    8385    auth_type_id_t       auth_type; 
    8486    unsigned             auth_key_len; 
     
    101103    /* plain RTP/RTCP (no cipher & no auth) */ 
    102104    {"NULL", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none}, 
    103 #if defined(PJMEDIA_SRTP_HAS_AES_GCM_256) && \ 
    104     (PJMEDIA_SRTP_HAS_AES_GCM_256 != 0) 
     105 
     106#if defined(PJMEDIA_SRTP_HAS_AES_GCM_256)&&(PJMEDIA_SRTP_HAS_AES_GCM_256!=0) 
     107 
    105108    /* cipher AES_GCM, NULL auth, auth tag len = 16 octets */ 
    106     {"AEAD_AES_256_GCM", AES_256_GCM, AES_256_GCM_KEYSIZE_WSALT, 
     109    {"AEAD_AES_256_GCM", AES_256_GCM, 44, 12, 
    107110        NULL_AUTH, 0, 16, 16, sec_serv_conf_and_auth, &aes_gcm_256_openssl}, 
     111 
    108112    /* cipher AES_GCM, NULL auth, auth tag len = 8 octets */ 
    109     {"AEAD_AES_256_GCM_8", AES_256_GCM, AES_256_GCM_KEYSIZE_WSALT, 
     113    {"AEAD_AES_256_GCM_8", AES_256_GCM, 44, 12, 
    110114        NULL_AUTH, 0, 8, 8, sec_serv_conf_and_auth, &aes_gcm_256_openssl}, 
    111115#endif 
    112 #if defined(PJMEDIA_SRTP_HAS_AES_CM_256) && \ 
    113     (PJMEDIA_SRTP_HAS_AES_CM_256 != 0) 
     116#if defined(PJMEDIA_SRTP_HAS_AES_CM_256)&&(PJMEDIA_SRTP_HAS_AES_CM_256!=0) 
     117 
    114118    /* cipher AES_CM_256, auth HMAC_SHA1, auth tag len = 10 octets */ 
    115     {"AES_256_CM_HMAC_SHA1_80", AES_ICM, 46, HMAC_SHA1, 20, 10, 10, 
     119    {"AES_256_CM_HMAC_SHA1_80", AES_ICM, 46, 14, HMAC_SHA1, 20, 10, 10, 
    116120        sec_serv_conf_and_auth, NULL,  
    117121        &crypto_policy_set_aes_cm_256_hmac_sha1_80}, 
     122 
    118123    /* cipher AES_CM_256, auth HMAC_SHA1, auth tag len = 10 octets */ 
    119     {"AES_256_CM_HMAC_SHA1_32", AES_ICM, 46, HMAC_SHA1, 20, 4, 10, 
     124    {"AES_256_CM_HMAC_SHA1_32", AES_ICM, 46, 14, HMAC_SHA1, 20, 4, 10, 
    120125        sec_serv_conf_and_auth, NULL, 
    121126        &crypto_policy_set_aes_cm_256_hmac_sha1_32}, 
    122127#endif 
    123 #if defined(PJMEDIA_SRTP_HAS_AES_CM_192) && \ 
    124     (PJMEDIA_SRTP_HAS_AES_CM_192 != 0) 
     128#if defined(PJMEDIA_SRTP_HAS_AES_CM_192)&&(PJMEDIA_SRTP_HAS_AES_CM_192!=0) 
     129 
    125130    /* cipher AES_CM_192, auth HMAC_SHA1, auth tag len = 10 octets */ 
    126     {"AES_192_CM_HMAC_SHA1_80", AES_ICM, 38, HMAC_SHA1, 20, 10, 10, 
     131    {"AES_192_CM_HMAC_SHA1_80", AES_ICM, 38, 14, HMAC_SHA1, 20, 10, 10, 
    127132        sec_serv_conf_and_auth, &aes_icm_192}, 
     133 
    128134    /* cipher AES_CM_192, auth HMAC_SHA1, auth tag len = 4 octets */ 
    129     {"AES_192_CM_HMAC_SHA1_32", AES_ICM, 38, HMAC_SHA1, 20, 4, 10, 
     135    {"AES_192_CM_HMAC_SHA1_32", AES_ICM, 38, 14, HMAC_SHA1, 20, 4, 10, 
    130136        sec_serv_conf_and_auth, &aes_icm_192}, 
    131137#endif 
    132 #if defined(PJMEDIA_SRTP_HAS_AES_GCM_128) && \ 
    133     (PJMEDIA_SRTP_HAS_AES_GCM_128 != 0) 
     138#if defined(PJMEDIA_SRTP_HAS_AES_GCM_128)&&(PJMEDIA_SRTP_HAS_AES_GCM_128!=0) 
     139 
    134140    /* cipher AES_GCM, NULL auth, auth tag len = 16 octets */ 
    135     {"AEAD_AES_128_GCM", AES_128_GCM, AES_128_GCM_KEYSIZE_WSALT, 
     141    {"AEAD_AES_128_GCM", AES_128_GCM, 28, 12, 
    136142        NULL_AUTH, 0, 16, 16, sec_serv_conf_and_auth, &aes_gcm_128_openssl}, 
    137143 
    138144    /* cipher AES_GCM, NULL auth, auth tag len = 8 octets */ 
    139     {"AEAD_AES_128_GCM_8", AES_128_GCM, AES_128_GCM_KEYSIZE_WSALT, 
     145    {"AEAD_AES_128_GCM_8", AES_128_GCM, 28, 12, 
    140146        NULL_AUTH, 0, 8, 8, sec_serv_conf_and_auth, &aes_gcm_128_openssl}, 
    141147#endif 
    142 #if defined(PJMEDIA_SRTP_HAS_AES_CM_128) && \ 
    143     (PJMEDIA_SRTP_HAS_AES_CM_128 != 0) 
     148#if defined(PJMEDIA_SRTP_HAS_AES_CM_128)&&(PJMEDIA_SRTP_HAS_AES_CM_128!=0) 
     149 
    144150    /* cipher AES_CM_128, auth HMAC_SHA1, auth tag len = 10 octets */ 
    145     {"AES_CM_128_HMAC_SHA1_80", AES_ICM, 30, HMAC_SHA1, 20, 10, 10, 
     151    {"AES_CM_128_HMAC_SHA1_80", AES_ICM, 30, 14, HMAC_SHA1, 20, 10, 10, 
    146152        sec_serv_conf_and_auth}, 
     153 
    147154    /* cipher AES_CM_128, auth HMAC_SHA1, auth tag len = 4 octets */ 
    148     {"AES_CM_128_HMAC_SHA1_32", AES_ICM, 30, HMAC_SHA1, 20, 4, 10, 
     155    {"AES_CM_128_HMAC_SHA1_32", AES_ICM, 30, 14, HMAC_SHA1, 20, 4, 10, 
    149156        sec_serv_conf_and_auth}, 
    150157#endif 
     158 
    151159    /* 
    152160     * F8_128_HMAC_SHA1_8 not supported by libsrtp? 
    153      * {"F8_128_HMAC_SHA1_8", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none} 
     161     * {"F8_128_HMAC_SHA1_8", NULL_CIPHER, 0, 0, NULL_AUTH, 0, 0, 0, 
     162     *  sec_serv_none} 
    154163     */ 
    155164}; 
    156165 
     166 
     167/* SRTP transport */ 
    157168typedef struct transport_srtp 
    158169{ 
     
    193204    /* Transport information */ 
    194205    pjmedia_transport   *member_tp; /**< Underlying transport.       */ 
     206    pj_bool_t            member_tp_attached; 
    195207 
    196208    /* SRTP usage policy of peer. This field is updated when media is starting. 
     
    205217     */ 
    206218    unsigned             probation_cnt; 
     219 
     220    /* SRTP keying methods. The keying is implemented using media transport 
     221     * abstraction, so it will also be invoked when the SRTP media transport 
     222     * operation is invoked. 
     223     * 
     224     * As there can be multiple keying methods enabled (currently only SDES & 
     225     * DTLS-SRTP), each keying method will be given the chance to respond to 
     226     * remote SDP. If any keying operation returns non-success, it will be 
     227     * removed from the session. And once SRTP key is obtained via a keying 
     228     * method, any other keying methods will be stopped and destroyed. 
     229     */ 
     230    unsigned             keying_cnt; 
     231    pjmedia_transport   *keying[2]; 
     232 
     233    /* If not zero, keying nego is ongoing (async-ly, e.g: by DTLS-SRTP). 
     234     * This field may be updated by keying method. 
     235     */ 
     236    unsigned             keying_pending_cnt; 
     237 
    207238} transport_srtp; 
    208239 
     
    224255static pj_status_t transport_get_info (pjmedia_transport *tp, 
    225256                                       pjmedia_transport_info *info); 
    226 static pj_status_t transport_attach   (pjmedia_transport *tp, 
    227                                        void *user_data, 
    228                                        const pj_sockaddr_t *rem_addr, 
    229                                        const pj_sockaddr_t *rem_rtcp, 
    230                                        unsigned addr_len, 
    231                                        void (*rtp_cb)(void*, 
    232                                                       void*, 
    233                                                       pj_ssize_t), 
    234                                        void (*rtcp_cb)(void*, 
    235                                                        void*, 
    236                                                        pj_ssize_t)); 
     257//static pj_status_t transport_attach   (pjmedia_transport *tp, 
     258//                                     void *user_data, 
     259//                                     const pj_sockaddr_t *rem_addr, 
     260//                                     const pj_sockaddr_t *rem_rtcp, 
     261//                                     unsigned addr_len, 
     262//                                     void (*rtp_cb)(void*, 
     263//                                                    void*, 
     264//                                                    pj_ssize_t), 
     265//                                     void (*rtcp_cb)(void*, 
     266//                                                     void*, 
     267//                                                     pj_ssize_t)); 
    237268static void        transport_detach   (pjmedia_transport *tp, 
    238269                                       void *strm); 
     
    268299                                       unsigned pct_lost); 
    269300static pj_status_t transport_destroy  (pjmedia_transport *tp); 
     301static pj_status_t transport_attach2  (pjmedia_transport *tp, 
     302                                       pjmedia_transport_attach_param *param); 
    270303 
    271304 
     
    274307{ 
    275308    &transport_get_info, 
    276     &transport_attach, 
     309    NULL, //&transport_attach, 
    277310    &transport_detach, 
    278311    &transport_send_rtp, 
     
    284317    &transport_media_stop, 
    285318    &transport_simulate_lost, 
    286     &transport_destroy 
     319    &transport_destroy, 
     320    &transport_attach2 
    287321}; 
     322 
     323/* Get crypto index from crypto name */ 
     324static int get_crypto_idx(const pj_str_t* crypto_name); 
     325 
     326/* Is crypto empty (i.e: no name or key)? */ 
     327static pj_bool_t srtp_crypto_empty(const pjmedia_srtp_crypto* c); 
     328 
     329/* Compare crypto, return zero if same */ 
     330static int srtp_crypto_cmp(const pjmedia_srtp_crypto* c1, 
     331                           const pjmedia_srtp_crypto* c2); 
     332 
     333/* Start SRTP */ 
     334static pj_status_t start_srtp(transport_srtp *srtp); 
     335 
     336/* SRTP keying method: Session Description */ 
     337#if defined(PJMEDIA_SRTP_HAS_SDES) && (PJMEDIA_SRTP_HAS_SDES != 0) 
     338#  include "transport_srtp_sdes.c" 
     339#endif 
     340 
     341/* SRTP keying method: DTLS */ 
     342#if defined(PJMEDIA_SRTP_HAS_DTLS) && (PJMEDIA_SRTP_HAS_DTLS != 0) 
     343#  include "transport_srtp_dtls.c" 
     344#endif 
     345 
    288346 
    289347/* This function may also be used by other module, e.g: pjmedia/errno.c, 
     
    346404PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt) 
    347405{ 
     406    pj_status_t status = PJ_SUCCESS; 
     407 
     408    if (libsrtp_initialized) 
     409        return PJ_SUCCESS; 
     410 
    348411#if PJMEDIA_LIBSRTP_AUTO_INIT_DEINIT 
    349     if (libsrtp_initialized == PJ_FALSE) { 
     412    /* Init libsrtp */ 
     413    { 
    350414        err_status_t err; 
    351415 
     
    356420            return PJMEDIA_ERRNO_FROM_LIBSRTP(err); 
    357421        } 
    358  
    359         if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS) 
    360         { 
    361             /* There will be memory leak when it fails to schedule libsrtp 
    362              * deinitialization, however the memory leak could be harmless, 
    363              * since in modern OS's memory used by an application is released 
    364              * when the application terminates. 
    365              */ 
    366             PJ_LOG(4, (THIS_FILE, "Failed to register libsrtp deinit.")); 
    367         } 
    368  
    369         libsrtp_initialized = PJ_TRUE; 
    370     } 
    371 #else 
    372     PJ_UNUSED_ARG(endpt); 
    373 #endif 
    374  
    375     return PJ_SUCCESS; 
     422    } 
     423#endif 
     424 
     425#if defined(PJMEDIA_SRTP_HAS_DTLS) && (PJMEDIA_SRTP_HAS_DTLS != 0) 
     426    dtls_init(); 
     427#endif 
     428 
     429    if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS) 
     430    { 
     431        /* There will be memory leak when it fails to schedule libsrtp 
     432         * deinitialization, however the memory leak could be harmless, 
     433         * since in modern OS's memory used by an application is released 
     434         * when the application terminates. 
     435         */ 
     436        PJ_LOG(4, (THIS_FILE, "Failed to register libsrtp deinit.")); 
     437    } 
     438 
     439    libsrtp_initialized = PJ_TRUE; 
     440 
     441    return status; 
    376442} 
    377443 
     
    392458# define PJMEDIA_SRTP_HAS_SHUTDOWN 1 
    393459#endif 
     460 
     461#if PJMEDIA_LIBSRTP_AUTO_INIT_DEINIT 
    394462 
    395463# if defined(PJMEDIA_SRTP_HAS_DEINIT) && PJMEDIA_SRTP_HAS_DEINIT!=0 
     
    404472                   get_libsrtp_errstr(err))); 
    405473    } 
     474#endif // PJMEDIA_LIBSRTP_AUTO_INIT_DEINIT 
     475 
     476#if defined(PJMEDIA_SRTP_HAS_DTLS) && (PJMEDIA_SRTP_HAS_DTLS != 0) 
     477    dtls_deinit(); 
     478#endif 
    406479 
    407480    libsrtp_initialized = PJ_FALSE; 
     
    464537    for (i=0; i<opt->crypto_count; ++i) 
    465538        opt->crypto[i].name = pj_str(crypto_suites[i+1].name); 
     539 
     540    /* Keying method */ 
     541    opt->keying_count = PJMEDIA_SRTP_KEYINGS_COUNT; 
     542    opt->keying[0] = PJMEDIA_SRTP_KEYING_SDES; 
     543    opt->keying[1] = PJMEDIA_SRTP_KEYING_DTLS_SRTP; 
     544 
     545    /* Just for reminder to add any new keying to the array above */ 
     546    pj_assert(PJMEDIA_SRTP_KEYINGS_COUNT == 2); 
    466547} 
    467548 
     
    551632        srtp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP; 
    552633    srtp->base.op = &transport_srtp_op; 
     634    srtp->base.user_data = srtp->setting.user_data; 
    553635 
    554636    /* Set underlying transport */ 
     
    557639    /* Initialize peer's SRTP usage mode. */ 
    558640    srtp->peer_use = srtp->setting.use; 
     641 
     642    /* Initialize SRTP keying method. */ 
     643    for (i = 0; i < srtp->setting.keying_count; ++i) { 
     644        switch(srtp->setting.keying[i]) { 
     645 
     646        case PJMEDIA_SRTP_KEYING_SDES: 
     647#if defined(PJMEDIA_SRTP_HAS_SDES) && (PJMEDIA_SRTP_HAS_SDES != 0) 
     648            sdes_create(srtp, &srtp->keying[srtp->keying_cnt++]); 
     649#endif 
     650            break; 
     651 
     652        case PJMEDIA_SRTP_KEYING_DTLS_SRTP: 
     653#if defined(PJMEDIA_SRTP_HAS_DTLS) && (PJMEDIA_SRTP_HAS_DTLS != 0) 
     654            dtls_create(srtp, &srtp->keying[srtp->keying_cnt++]); 
     655#endif 
     656            break; 
     657 
     658        default: 
     659            break; 
     660        } 
     661    } 
    559662 
    560663    /* Done */ 
     
    780883} 
    781884 
     885 
     886static pj_status_t start_srtp(transport_srtp *srtp) 
     887{ 
     888    /* Make sure we have the SRTP policies */ 
     889    if (srtp_crypto_empty(&srtp->tx_policy_neg) || 
     890        srtp_crypto_empty(&srtp->rx_policy_neg)) 
     891    { 
     892        srtp->bypass_srtp = PJ_TRUE; 
     893        srtp->peer_use = PJMEDIA_SRTP_DISABLED; 
     894        if (srtp->session_inited) { 
     895            pjmedia_transport_srtp_stop(&srtp->base); 
     896        } 
     897 
     898        return PJ_SUCCESS; 
     899    } 
     900 
     901    /* Reset probation counts */ 
     902    srtp->probation_cnt = PROBATION_CNT_INIT; 
     903 
     904    /* Got policy_local & policy_remote, let's initalize the SRTP */ 
     905 
     906    /* Ticket #1075: media_start() is called whenever media description 
     907     * gets updated, e.g: call hold, however we should restart SRTP only 
     908     * when the SRTP policy settings are updated. 
     909     */ 
     910    if (srtp_crypto_cmp(&srtp->tx_policy_neg, &srtp->tx_policy) || 
     911        srtp_crypto_cmp(&srtp->rx_policy_neg, &srtp->rx_policy)) 
     912    { 
     913        pj_status_t status; 
     914        status = pjmedia_transport_srtp_start(&srtp->base, 
     915                                              &srtp->tx_policy_neg, 
     916                                              &srtp->rx_policy_neg); 
     917        if (status != PJ_SUCCESS) 
     918            return status; 
     919    } 
     920 
     921    srtp->bypass_srtp = PJ_FALSE; 
     922 
     923    return PJ_SUCCESS; 
     924} 
     925 
     926 
    782927PJ_DEF(pjmedia_transport *) pjmedia_transport_srtp_get_member( 
    783928                                                pjmedia_transport *tp) 
     
    797942    pjmedia_srtp_info srtp_info; 
    798943    int spc_info_idx; 
     944    unsigned i; 
    799945 
    800946    PJ_ASSERT_RETURN(tp && info, PJ_EINVAL); 
     
    816962              sizeof(srtp_info)); 
    817963 
     964    /* Invoke get_info() of all keying methods */ 
     965    for (i=0; i < srtp->keying_cnt; i++) 
     966        pjmedia_transport_get_info(srtp->keying[i], info); 
     967 
    818968    return pjmedia_transport_get_info(srtp->member_tp, info); 
    819969} 
    820970 
    821 static pj_status_t transport_attach(pjmedia_transport *tp, 
    822                                     void *user_data, 
    823                                     const pj_sockaddr_t *rem_addr, 
    824                                     const pj_sockaddr_t *rem_rtcp, 
    825                                     unsigned addr_len, 
    826                                     void (*rtp_cb) (void*, void*, 
    827                                                     pj_ssize_t), 
    828                                     void (*rtcp_cb)(void*, void*, 
    829                                                     pj_ssize_t)) 
     971static pj_status_t transport_attach2(pjmedia_transport *tp, 
     972                                     pjmedia_transport_attach_param *param) 
    830973{ 
    831974    transport_srtp *srtp = (transport_srtp*) tp; 
     975    pjmedia_transport_attach_param member_param; 
    832976    pj_status_t status; 
    833977 
    834     PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL); 
     978    PJ_ASSERT_RETURN(tp && param, PJ_EINVAL); 
    835979 
    836980    /* Save the callbacks */ 
    837981    pj_lock_acquire(srtp->mutex); 
    838     srtp->rtp_cb = rtp_cb; 
    839     srtp->rtcp_cb = rtcp_cb; 
    840     srtp->user_data = user_data; 
     982    srtp->rtp_cb = param->rtp_cb; 
     983    srtp->rtcp_cb = param->rtcp_cb; 
     984    srtp->user_data = param->user_data; 
    841985    pj_lock_release(srtp->mutex); 
    842986 
    843     /* Attach itself to transport */ 
    844     status = pjmedia_transport_attach(srtp->member_tp, srtp, rem_addr, 
    845                                       rem_rtcp, addr_len, &srtp_rtp_cb, 
    846                                       &srtp_rtcp_cb); 
     987    /* Attach self to member transport */ 
     988    member_param = *param; 
     989    member_param.user_data = srtp; 
     990    member_param.rtp_cb = &srtp_rtp_cb; 
     991    member_param.rtcp_cb = &srtp_rtcp_cb; 
     992    status = pjmedia_transport_attach2(srtp->member_tp, &member_param); 
    847993    if (status != PJ_SUCCESS) { 
    848994        pj_lock_acquire(srtp->mutex); 
     
    8541000    } 
    8551001 
     1002    srtp->member_tp_attached = PJ_TRUE; 
    8561003    return PJ_SUCCESS; 
    8571004} 
     
    8741021    srtp->user_data = NULL; 
    8751022    pj_lock_release(srtp->mutex); 
     1023    srtp->member_tp_attached = PJ_FALSE; 
    8761024} 
    8771025 
     
    9731121    transport_srtp *srtp = (transport_srtp *) tp; 
    9741122    pj_status_t status; 
     1123    unsigned i; 
    9751124 
    9761125    PJ_ASSERT_RETURN(tp, PJ_EINVAL); 
    9771126 
     1127    /* Close keying */ 
     1128    for (i=0; i < srtp->keying_cnt; i++) 
     1129        pjmedia_transport_close(srtp->keying[i]); 
     1130 
     1131    /* Close member if configured */ 
    9781132    if (srtp->setting.close_member_tp && srtp->member_tp) { 
    9791133        pjmedia_transport_close(srtp->member_tp); 
     
    10101164    if (size < 0) { 
    10111165        return; 
     1166    } 
     1167 
     1168    /* Give the packet to keying first by invoking its send_rtp() op. 
     1169     * Yes, the usage of send_rtp() is rather hacky, but it is convenient 
     1170     * as the signature suits the purpose and it is ready to use 
     1171     * (no futher registration/setting needed), and it may never be used 
     1172     * by any keying method in the future. 
     1173     */ 
     1174    { 
     1175        unsigned i; 
     1176        pj_status_t status; 
     1177        for (i=0; i < srtp->keying_cnt; i++) { 
     1178            if (!srtp->keying[i]->op->send_rtp) 
     1179                continue; 
     1180            status = pjmedia_transport_send_rtp(srtp->keying[i], pkt, size); 
     1181            if (status != PJ_EIGNORED) { 
     1182                /* Packet is already consumed by the keying method */ 
     1183                return; 
     1184            } 
     1185        } 
    10121186    } 
    10131187 
     
    11111285} 
    11121286 
    1113 /* Generate crypto attribute, including crypto key. 
    1114  * If crypto-suite chosen is crypto NULL, just return PJ_SUCCESS, 
    1115  * and set buffer_len = 0. 
    1116  */ 
    1117 static pj_status_t generate_crypto_attr_value(pj_pool_t *pool, 
    1118                                               char *buffer, int *buffer_len, 
    1119                                               pjmedia_srtp_crypto *crypto, 
    1120                                               int tag) 
    1121 { 
    1122     pj_status_t status; 
    1123     int cs_idx = get_crypto_idx(&crypto->name); 
    1124     char b64_key[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)+1]; 
    1125     int b64_key_len = sizeof(b64_key); 
    1126     int print_len; 
    1127  
    1128     if (cs_idx == -1) 
    1129         return PJMEDIA_SRTP_ENOTSUPCRYPTO; 
    1130  
    1131     /* Crypto-suite NULL. */ 
    1132     if (cs_idx == 0) { 
    1133         *buffer_len = 0; 
    1134         return PJ_SUCCESS; 
    1135     } 
    1136  
    1137     /* Generate key if not specified. */ 
    1138     if (crypto->key.slen == 0) { 
    1139         pj_bool_t key_ok; 
    1140         char key[MAX_KEY_LEN]; 
    1141         err_status_t err; 
    1142         unsigned i; 
    1143  
    1144         PJ_ASSERT_RETURN(MAX_KEY_LEN >= crypto_suites[cs_idx].cipher_key_len, 
    1145                          PJ_ETOOSMALL); 
    1146  
    1147         do { 
    1148             key_ok = PJ_TRUE; 
    1149  
    1150  
    1151 #if defined(PJ_HAS_SSL_SOCK) && (PJ_HAS_SSL_SOCK != 0) 
    1152  
    1153 /* Include OpenSSL libraries for MSVC */ 
    1154 #  ifdef _MSC_VER 
    1155 #    if OPENSSL_VERSION_NUMBER >= 0x10100000L 
    1156 #      pragma comment(lib, "libcrypto") 
    1157 #    else 
    1158 #      pragma comment(lib, "libeay32") 
    1159 #      pragma comment(lib, "ssleay32") 
    1160 #    endif 
    1161 #  endif 
    1162  
    1163             err = RAND_bytes((unsigned char*)key, 
    1164                              crypto_suites[cs_idx].cipher_key_len); 
    1165             if (err != 1) { 
    1166                 PJ_LOG(5,(THIS_FILE, "Failed generating random key")); 
    1167                 return PJMEDIA_ERRNO_FROM_LIBSRTP(1); 
    1168             } 
    1169 #else        
    1170             err = crypto_get_random((unsigned char*)key, 
    1171                                      crypto_suites[cs_idx].cipher_key_len); 
    1172             if (err != err_status_ok) { 
    1173                 PJ_LOG(5,(THIS_FILE, "Failed generating random key: %s", 
    1174                           get_libsrtp_errstr(err))); 
    1175                 return PJMEDIA_ERRNO_FROM_LIBSRTP(err); 
    1176             } 
    1177 #endif 
    1178             for (i=0; i<crypto_suites[cs_idx].cipher_key_len && key_ok; ++i) 
    1179                 if (key[i] == 0) key_ok = PJ_FALSE; 
    1180  
    1181         } while (!key_ok); 
    1182         crypto->key.ptr = (char*) 
    1183                           pj_pool_zalloc(pool, 
    1184                                          crypto_suites[cs_idx].cipher_key_len); 
    1185         pj_memcpy(crypto->key.ptr, key, crypto_suites[cs_idx].cipher_key_len); 
    1186         crypto->key.slen = crypto_suites[cs_idx].cipher_key_len; 
    1187     } 
    1188  
    1189     if (crypto->key.slen != (pj_ssize_t)crypto_suites[cs_idx].cipher_key_len) 
    1190         return PJMEDIA_SRTP_EINKEYLEN; 
    1191  
    1192     /* Key transmitted via SDP should be base64 encoded. */ 
    1193     status = pj_base64_encode((pj_uint8_t*)crypto->key.ptr, crypto->key.slen, 
    1194                               b64_key, &b64_key_len); 
    1195     if (status != PJ_SUCCESS) { 
    1196         PJ_LOG(5,(THIS_FILE, "Failed encoding plain key to base64")); 
    1197         return status; 
    1198     } 
    1199  
    1200     b64_key[b64_key_len] = '\0'; 
    1201  
    1202     PJ_ASSERT_RETURN(*buffer_len >= (crypto->name.slen + \ 
    1203                      b64_key_len + 16), PJ_ETOOSMALL); 
    1204  
    1205     /* Print the crypto attribute value. */ 
    1206     print_len = pj_ansi_snprintf(buffer, *buffer_len, "%d %s inline:%s", 
    1207                                    tag, 
    1208                                    crypto_suites[cs_idx].name, 
    1209                                    b64_key); 
    1210     if (print_len < 1 || print_len >= *buffer_len) 
    1211         return PJ_ETOOSMALL; 
    1212  
    1213     *buffer_len = print_len; 
    1214  
    1215     return PJ_SUCCESS; 
    1216 } 
    1217  
    1218 /* Parse crypto attribute line */ 
    1219 static pj_status_t parse_attr_crypto(pj_pool_t *pool, 
    1220                                      const pjmedia_sdp_attr *attr, 
    1221                                      pjmedia_srtp_crypto *crypto, 
    1222                                      int *tag) 
    1223 { 
    1224     pj_str_t token, delim; 
    1225     pj_status_t status; 
    1226     int itmp, found_idx; 
    1227  
    1228     pj_bzero(crypto, sizeof(*crypto)); 
    1229  
    1230     /* Tag */ 
    1231     delim = pj_str(" "); 
    1232     found_idx = pj_strtok(&attr->value, &delim, &token, 0); 
    1233     if (found_idx == attr->value.slen) { 
    1234         PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting tag")); 
    1235         return PJMEDIA_SDP_EINATTR; 
    1236     } 
    1237  
    1238     /* Tag must not use leading zeroes. */ 
    1239     if (token.slen > 1 && *token.ptr == '0') 
    1240         return PJMEDIA_SDP_EINATTR; 
    1241  
    1242     /* Tag must be decimal, i.e: contains only digit '0'-'9'. */ 
    1243     for (itmp = 0; itmp < token.slen; ++itmp) 
    1244         if (!pj_isdigit(token.ptr[itmp])) 
    1245             return PJMEDIA_SDP_EINATTR; 
    1246  
    1247     /* Get tag value. */ 
    1248     *tag = pj_strtoul(&token); 
    1249  
    1250     /* Crypto-suite */ 
    1251     found_idx = pj_strtok(&attr->value, &delim, &token, found_idx+token.slen); 
    1252     if (found_idx == attr->value.slen) { 
    1253         PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting crypto suite")); 
    1254         return PJMEDIA_SDP_EINATTR; 
    1255     } 
    1256     pj_strdup(pool, &crypto->name, &token);     
    1257  
    1258     /* Key method */ 
    1259     delim = pj_str(": "); 
    1260     found_idx = pj_strtok(&attr->value, &delim, &token, found_idx+token.slen); 
    1261     if (found_idx == attr->value.slen) { 
    1262         PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key method")); 
    1263         return PJMEDIA_SDP_EINATTR; 
    1264     } 
    1265     if (pj_stricmp2(&token, "inline")) { 
    1266         PJ_LOG(4,(THIS_FILE, "Attribute crypto key method '%.*s' " 
    1267                   "not supported!", token.slen, token.ptr)); 
    1268         return PJMEDIA_SDP_EINATTR; 
    1269     } 
    1270  
    1271     /* Key */     
    1272     delim = pj_str("| "); 
    1273     found_idx = pj_strtok(&attr->value, &delim, &token, found_idx+token.slen); 
    1274     if (found_idx == attr->value.slen) { 
    1275         PJ_LOG(4,(THIS_FILE, "Attribute crypto expecting key")); 
    1276         return PJMEDIA_SDP_EINATTR; 
    1277     } 
    1278      
    1279     if (PJ_BASE64_TO_BASE256_LEN(token.slen) > MAX_KEY_LEN) { 
    1280         PJ_LOG(4,(THIS_FILE, "Key too long")); 
    1281         return PJMEDIA_SRTP_EINKEYLEN; 
    1282     } 
    1283  
    1284     /* Decode key */ 
    1285     crypto->key.ptr = (char*) pj_pool_zalloc(pool, MAX_KEY_LEN); 
    1286     itmp = MAX_KEY_LEN; 
    1287     status = pj_base64_decode(&token, (pj_uint8_t*)crypto->key.ptr, 
    1288                               &itmp); 
    1289     if (status != PJ_SUCCESS) { 
    1290         PJ_LOG(4,(THIS_FILE, "Failed decoding crypto key from base64")); 
    1291         return status; 
    1292     } 
    1293     crypto->key.slen = itmp; 
    1294  
    1295     return PJ_SUCCESS; 
    1296 } 
    12971287 
    12981288static pj_status_t transport_media_create(pjmedia_transport *tp, 
     
    13041294    struct transport_srtp *srtp = (struct transport_srtp*) tp; 
    13051295    unsigned member_tp_option; 
     1296    pj_status_t last_err_st = PJ_EBUG; 
     1297    pj_status_t status; 
     1298    unsigned i; 
    13061299 
    13071300    PJ_ASSERT_RETURN(tp, PJ_EINVAL); 
     
    13101303    pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg)); 
    13111304 
    1312     srtp->media_option = options; 
    1313     member_tp_option = options | PJMEDIA_TPMED_NO_TRANSPORT_CHECKING; 
    1314  
    1315     srtp->offerer_side = sdp_remote == NULL; 
    1316  
    1317     /* Validations */ 
    1318     if (srtp->offerer_side) { 
    1319  
    1320         if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) 
    1321             goto BYPASS_SRTP; 
    1322  
    1323     } else { 
    1324  
    1325         pjmedia_sdp_media *m_rem; 
    1326  
    1327         m_rem = sdp_remote->media[media_index]; 
    1328  
    1329         /* Nothing to do on inactive media stream */ 
    1330         if (pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL)) 
    1331             goto BYPASS_SRTP; 
    1332  
    1333         /* Validate remote media transport based on SRTP usage option. 
    1334          */ 
    1335         switch (srtp->setting.use) { 
    1336             case PJMEDIA_SRTP_DISABLED: 
    1337                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) 
    1338                     return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    1339                 goto BYPASS_SRTP; 
    1340             case PJMEDIA_SRTP_OPTIONAL: 
    1341                 break; 
    1342             case PJMEDIA_SRTP_MANDATORY: 
    1343                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0) 
    1344                     return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    1345                 break; 
     1305    srtp->media_option = member_tp_option = options; 
     1306    srtp->offerer_side = (sdp_remote == NULL); 
     1307 
     1308    if (srtp->offerer_side && srtp->setting.use == PJMEDIA_SRTP_DISABLED) 
     1309        srtp->bypass_srtp = PJ_TRUE; 
     1310    else 
     1311        member_tp_option |= PJMEDIA_TPMED_NO_TRANSPORT_CHECKING; 
     1312 
     1313    status = pjmedia_transport_media_create(srtp->member_tp, sdp_pool, 
     1314                                            member_tp_option, sdp_remote, 
     1315                                            media_index); 
     1316    if (status != PJ_SUCCESS || srtp->bypass_srtp) 
     1317        return status; 
     1318 
     1319    /* Invoke media_create() of all keying methods */ 
     1320    for (i=0; i < srtp->keying_cnt; ) { 
     1321        pj_status_t st; 
     1322        st = pjmedia_transport_media_create(srtp->keying[i], sdp_pool, 
     1323                                            options, sdp_remote, 
     1324                                            media_index); 
     1325        if (st != PJ_SUCCESS) { 
     1326            /* This keying method returns error, remove it */ 
     1327            pj_array_erase(srtp->keying, sizeof(srtp->keying[0]), 
     1328                           srtp->keying_cnt, i); 
     1329            srtp->keying_cnt--; 
     1330            last_err_st = st; 
     1331            continue; 
     1332        } else if (srtp->offerer_side) { 
     1333            /* Currently we can send one keying only in outgoing offer */ 
     1334            srtp->keying[0] = srtp->keying[i]; 
     1335            srtp->keying_cnt = 1; 
     1336            break; 
    13461337        } 
    13471338 
    1348     } 
    1349     goto PROPAGATE_MEDIA_CREATE; 
    1350  
    1351 BYPASS_SRTP: 
    1352     srtp->bypass_srtp = PJ_TRUE; 
    1353     member_tp_option &= ~PJMEDIA_TPMED_NO_TRANSPORT_CHECKING; 
    1354  
    1355 PROPAGATE_MEDIA_CREATE: 
    1356     return pjmedia_transport_media_create(srtp->member_tp, sdp_pool, 
    1357                                           member_tp_option, sdp_remote, 
    1358                                           media_index); 
     1339        ++i; 
     1340    } 
     1341 
     1342    /* All keying method failed to process remote SDP? */ 
     1343    if (srtp->keying_cnt == 0) 
     1344        return last_err_st; 
     1345 
     1346    return PJ_SUCCESS; 
    13591347} 
    13601348 
     
    13661354{ 
    13671355    struct transport_srtp *srtp = (struct transport_srtp*) tp; 
    1368     pjmedia_sdp_media *m_rem, *m_loc; 
    1369     enum { MAXLEN = 512 }; 
    1370     char buffer[MAXLEN]; 
    1371     int buffer_len; 
     1356    pj_status_t last_err_st = PJ_EBUG; 
    13721357    pj_status_t status; 
    1373     pjmedia_sdp_attr *attr; 
    1374     pj_str_t attr_value; 
    1375     unsigned i, j; 
     1358    unsigned i; 
    13761359 
    13771360    PJ_ASSERT_RETURN(tp && sdp_pool && sdp_local, PJ_EINVAL); 
     
    13801363    pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg)); 
    13811364 
    1382     srtp->offerer_side = sdp_remote == NULL; 
    1383  
    1384     m_rem = sdp_remote ? sdp_remote->media[media_index] : NULL; 
    1385     m_loc = sdp_local->media[media_index]; 
    1386  
    1387     /* Bypass if media transport is not RTP/AVP or RTP/SAVP */ 
    1388     if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP)  != 0 && 
    1389         pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0) 
    1390         goto BYPASS_SRTP; 
    1391  
    1392     /* If the media is inactive, do nothing. */ 
    1393     /* No, we still need to process SRTP offer/answer even if the media is 
    1394      * marked as inactive, because the transport is still alive in this 
    1395      * case (e.g. for keep-alive). See: 
    1396      *   http://trac.pjsip.org/repos/ticket/1079 
    1397      */ 
    1398     /* 
    1399     if (pjmedia_sdp_media_find_attr(m_loc, &ID_INACTIVE, NULL) || 
    1400         (m_rem && pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL))) 
    1401         goto BYPASS_SRTP; 
    1402     */ 
    1403  
    1404     /* Check remote media transport & set local media transport 
    1405      * based on SRTP usage option. 
    1406      */ 
    1407     if (srtp->offerer_side) { 
    1408  
    1409         /* Generate transport */ 
    1410         switch (srtp->setting.use) { 
    1411             case PJMEDIA_SRTP_DISABLED: 
    1412                 goto BYPASS_SRTP; 
    1413             case PJMEDIA_SRTP_OPTIONAL: 
    1414                 m_loc->desc.transport = 
    1415                                 (srtp->peer_use == PJMEDIA_SRTP_MANDATORY)? 
    1416                                 ID_RTP_SAVP : ID_RTP_AVP; 
    1417                 break; 
    1418             case PJMEDIA_SRTP_MANDATORY: 
    1419                 m_loc->desc.transport = ID_RTP_SAVP; 
    1420                 break; 
     1365    srtp->offerer_side = (sdp_remote == NULL); 
     1366 
     1367    status = pjmedia_transport_encode_sdp(srtp->member_tp, sdp_pool, 
     1368                                          sdp_local, sdp_remote, media_index); 
     1369    if (status != PJ_SUCCESS || srtp->bypass_srtp) 
     1370        return status; 
     1371 
     1372    /* Invoke encode_sdp() of all keying methods */ 
     1373    for (i=0; i < srtp->keying_cnt; ) { 
     1374        pj_status_t st; 
     1375        st = pjmedia_transport_encode_sdp(srtp->keying[i], sdp_pool, 
     1376                                          sdp_local, sdp_remote, 
     1377                                          media_index); 
     1378        if (st != PJ_SUCCESS) { 
     1379            /* This keying method returns error, remove it */ 
     1380            pj_array_erase(srtp->keying, sizeof(srtp->keying[0]), 
     1381                           srtp->keying_cnt, i); 
     1382            srtp->keying_cnt--; 
     1383            last_err_st = st; 
     1384            continue; 
    14211385        } 
    14221386 
    1423         /* Generate crypto attribute if not yet */ 
    1424         if (pjmedia_sdp_media_find_attr(m_loc, &ID_CRYPTO, NULL) == NULL) { 
    1425             int tag = 1; 
    1426  
    1427             /* Offer only current active crypto if any, otherwise offer all 
    1428              * crypto-suites in the setting. 
    1429              */ 
    1430             for (i=0; i<srtp->setting.crypto_count; ++i) { 
    1431                 if (srtp->tx_policy.name.slen && 
    1432                     pj_stricmp(&srtp->tx_policy.name, 
    1433                                &srtp->setting.crypto[i].name) != 0) 
    1434                 { 
    1435                     continue; 
    1436                 } 
    1437  
    1438                 buffer_len = MAXLEN; 
    1439                 status = generate_crypto_attr_value(srtp->pool, buffer, &buffer_len, 
    1440                                                     &srtp->setting.crypto[i], 
    1441                                                     tag); 
    1442                 if (status != PJ_SUCCESS) 
    1443                     return status; 
    1444  
    1445                 /* If buffer_len==0, just skip the crypto attribute. */ 
    1446                 if (buffer_len) { 
    1447                     pj_strset(&attr_value, buffer, buffer_len); 
    1448                     attr = pjmedia_sdp_attr_create(srtp->pool, ID_CRYPTO.ptr, 
    1449                                                    &attr_value); 
    1450                     m_loc->attr[m_loc->attr_count++] = attr; 
    1451                     ++tag; 
    1452                 } 
     1387        if (!srtp_crypto_empty(&srtp->tx_policy_neg) && 
     1388            !srtp_crypto_empty(&srtp->rx_policy_neg)) 
     1389        { 
     1390            /* SRTP nego is done, let's destroy any other keying. */ 
     1391            unsigned j; 
     1392            for (j = 0; j < srtp->keying_cnt; ++j) { 
     1393                if (j != i) 
     1394                    pjmedia_transport_close(srtp->keying[j]); 
    14531395            } 
     1396            srtp->keying_cnt = 1; 
     1397            srtp->keying[0] = srtp->keying[i]; 
     1398            srtp->keying_pending_cnt = 0; 
     1399            break; 
    14541400        } 
    14551401 
    1456     } else { 
    1457         /* Answerer side */ 
    1458  
    1459         pj_assert(sdp_remote && m_rem); 
    1460  
    1461         /* Generate transport */ 
    1462         switch (srtp->setting.use) { 
    1463             case PJMEDIA_SRTP_DISABLED: 
    1464                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) 
    1465                     return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    1466                 goto BYPASS_SRTP; 
    1467             case PJMEDIA_SRTP_OPTIONAL: 
    1468                 m_loc->desc.transport = m_rem->desc.transport; 
    1469                 break; 
    1470             case PJMEDIA_SRTP_MANDATORY: 
    1471                 if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) != 0) 
    1472                     return PJMEDIA_SRTP_ESDPINTRANSPORT; 
    1473                 m_loc->desc.transport = ID_RTP_SAVP; 
    1474                 break; 
    1475         } 
    1476  
    1477         /* Generate crypto attribute if not yet */ 
    1478         if (pjmedia_sdp_media_find_attr(m_loc, &ID_CRYPTO, NULL) == NULL) { 
    1479  
    1480             pjmedia_srtp_crypto tmp_rx_crypto; 
    1481             pj_bool_t has_crypto_attr = PJ_FALSE; 
    1482             int matched_idx = -1; 
    1483             int chosen_tag = 0; 
    1484             int tags[64]; /* assume no more than 64 crypto attrs in a media */ 
    1485             unsigned cr_attr_count = 0; 
    1486  
    1487             /* Find supported crypto-suite, get the tag, and assign policy_local */ 
    1488             for (i=0; i<m_rem->attr_count; ++i) { 
    1489                 if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0) 
    1490                     continue; 
    1491  
    1492                 has_crypto_attr = PJ_TRUE; 
    1493  
    1494                 status = parse_attr_crypto(srtp->pool, m_rem->attr[i], 
    1495                                            &tmp_rx_crypto, &tags[cr_attr_count]); 
    1496                 if (status != PJ_SUCCESS) 
    1497                     return status; 
    1498  
    1499                 /* Check duplicated tag */ 
    1500                 for (j=0; j<cr_attr_count; ++j) { 
    1501                     if (tags[j] == tags[cr_attr_count]) { 
    1502                         DEACTIVATE_MEDIA(sdp_pool, m_loc); 
    1503                         return PJMEDIA_SRTP_ESDPDUPCRYPTOTAG; 
    1504                     } 
    1505                 } 
    1506  
    1507                 if (matched_idx == -1) { 
    1508                     /* lets see if the crypto-suite offered is supported */ 
    1509                     for (j=0; j<srtp->setting.crypto_count; ++j) 
    1510                         if (pj_stricmp(&tmp_rx_crypto.name, 
    1511                                        &srtp->setting.crypto[j].name) == 0) 
    1512                         { 
    1513                             int cs_idx = get_crypto_idx(&tmp_rx_crypto.name); 
    1514                              
    1515                             if (cs_idx == -1) 
    1516                                 return PJMEDIA_SRTP_ENOTSUPCRYPTO; 
    1517  
    1518                             /* Force to use test key */ 
    1519                             /* bad keys for snom: */ 
    1520                             //char *hex_test_key = "58b29c5c8f42308120ce857e439f2d" 
    1521                             //               "7810a8b10ad0b1446be5470faea496"; 
    1522                             //char *hex_test_key = "20a26aac7ba062d356ff52b61e3993" 
    1523                             //               "ccb78078f12c64db94b9c294927fd0"; 
    1524                             //pj_str_t *test_key = &srtp->setting.crypto[j].key; 
    1525                             //char  *raw_test_key = pj_pool_zalloc(srtp->pool, 64); 
    1526                             //hex_string_to_octet_string( 
    1527                             //          raw_test_key, 
    1528                             //          hex_test_key, 
    1529                             //          strlen(hex_test_key)); 
    1530                             //pj_strset(test_key, raw_test_key, 
    1531                             //    crypto_suites[cs_idx].cipher_key_len); 
    1532                             /* EO Force to use test key */ 
    1533  
    1534                             if (tmp_rx_crypto.key.slen != 
    1535                                 (int)crypto_suites[cs_idx].cipher_key_len) 
    1536                                 return PJMEDIA_SRTP_EINKEYLEN; 
    1537  
    1538                             srtp->rx_policy_neg = tmp_rx_crypto; 
    1539                             chosen_tag = tags[cr_attr_count]; 
    1540                             matched_idx = j; 
    1541                             break; 
    1542                         } 
    1543                 } 
    1544                 cr_attr_count++; 
    1545             } 
    1546  
    1547             /* Check crypto negotiation result */ 
    1548             switch (srtp->setting.use) { 
    1549                 case PJMEDIA_SRTP_DISABLED: 
    1550                     pj_assert(!"Should never reach here"); 
    1551                     break; 
    1552  
    1553                 case PJMEDIA_SRTP_OPTIONAL: 
    1554                     /* bypass SRTP when no crypto-attr and remote uses RTP/AVP */ 
    1555                     if (!has_crypto_attr && 
    1556                         pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0) 
    1557                         goto BYPASS_SRTP; 
    1558                     /* bypass SRTP when nothing match and remote uses RTP/AVP */ 
    1559                     else if (matched_idx == -1 && 
    1560                         pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0) 
    1561                         goto BYPASS_SRTP; 
    1562                     break; 
    1563  
    1564                 case PJMEDIA_SRTP_MANDATORY: 
    1565                     /* Do nothing, intentional */ 
    1566                     break; 
    1567             } 
    1568  
    1569             /* No crypto attr */ 
    1570             if (!has_crypto_attr) { 
    1571                 DEACTIVATE_MEDIA(sdp_pool, m_loc); 
    1572                 return PJMEDIA_SRTP_ESDPREQCRYPTO; 
    1573             } 
    1574  
    1575             /* No crypto match */ 
    1576             if (matched_idx == -1) { 
    1577                 DEACTIVATE_MEDIA(sdp_pool, m_loc); 
    1578                 return PJMEDIA_SRTP_ENOTSUPCRYPTO; 
    1579             } 
    1580  
    1581             /* we have to generate crypto answer, 
    1582              * with srtp->tx_policy_neg matched the offer 
    1583              * and rem_tag contains matched offer tag. 
    1584              */ 
    1585             buffer_len = MAXLEN; 
    1586             status = generate_crypto_attr_value(srtp->pool, buffer, &buffer_len, 
    1587                                                 &srtp->setting.crypto[matched_idx], 
    1588                                                 chosen_tag); 
    1589             if (status != PJ_SUCCESS) 
    1590                 return status; 
    1591  
    1592             srtp->tx_policy_neg = srtp->setting.crypto[matched_idx]; 
    1593  
    1594             /* If buffer_len==0, just skip the crypto attribute. */ 
    1595             if (buffer_len) { 
    1596                 pj_strset(&attr_value, buffer, buffer_len); 
    1597                 attr = pjmedia_sdp_attr_create(sdp_pool, ID_CRYPTO.ptr, 
    1598                                                &attr_value); 
    1599                 m_loc->attr[m_loc->attr_count++] = attr; 
    1600             } 
    1601  
    1602             /* At this point, we get valid rx_policy_neg & tx_policy_neg. */ 
    1603         } 
    1604  
    1605     } 
    1606     goto PROPAGATE_MEDIA_CREATE; 
    1607  
    1608 BYPASS_SRTP: 
    1609     /* Do not update this flag here as actually the media session hasn't been 
    1610      * updated. 
    1611      */ 
    1612     //srtp->bypass_srtp = PJ_TRUE; 
    1613  
    1614 PROPAGATE_MEDIA_CREATE: 
    1615     return pjmedia_transport_encode_sdp(srtp->member_tp, sdp_pool, 
    1616                                         sdp_local, sdp_remote, media_index); 
    1617 } 
    1618  
    1619  
    1620 static pj_status_t fill_local_crypto(pj_pool_t *pool, 
    1621                                      const pjmedia_sdp_media *m_loc,  
    1622                                      pjmedia_srtp_crypto loc_crypto[], 
    1623                                      int *count) 
    1624 { 
    1625     int i; 
    1626     int crypto_count = 0; 
    1627     pj_status_t status = PJ_SUCCESS; 
    1628      
    1629     for (i = 0; i < *count; ++i) { 
    1630         pj_bzero(&loc_crypto[i], sizeof(loc_crypto[i])); 
    1631     } 
    1632  
    1633     for (i = 0; i < (int)m_loc->attr_count; ++i) {       
    1634         pjmedia_srtp_crypto tmp_crypto; 
    1635         int loc_tag; 
    1636  
    1637         if (pj_stricmp(&m_loc->attr[i]->name, &ID_CRYPTO) != 0) 
    1638             continue; 
    1639  
    1640         status = parse_attr_crypto(pool, m_loc->attr[i], 
    1641                                    &tmp_crypto, &loc_tag); 
    1642         if (status != PJ_SUCCESS) 
    1643             return status; 
    1644  
    1645         if (loc_tag > *count) 
    1646             return PJMEDIA_SRTP_ESDPINCRYPTOTAG; 
    1647  
    1648         loc_crypto[loc_tag-1] = tmp_crypto; 
    1649         ++crypto_count; 
    1650     } 
    1651     *count = crypto_count; 
    1652     return status; 
     1402        i++; 
     1403    } 
     1404 
     1405    /* All keying method failed to process remote SDP? */ 
     1406    if (srtp->keying_cnt == 0) 
     1407        return last_err_st; 
     1408 
     1409    return PJ_SUCCESS; 
    16531410} 
    16541411 
     
    16611418{ 
    16621419    struct transport_srtp *srtp = (struct transport_srtp*) tp; 
    1663     pjmedia_sdp_media *m_rem, *m_loc; 
     1420    pj_status_t last_err_st = PJ_EBUG; 
    16641421    pj_status_t status; 
    16651422    unsigned i; 
    1666     pjmedia_srtp_crypto loc_crypto[PJMEDIA_SRTP_MAX_CRYPTOS]; 
    1667     int loc_cryto_cnt = PJMEDIA_SRTP_MAX_CRYPTOS; 
    16681423 
    16691424    PJ_ASSERT_RETURN(tp && pool && sdp_local && sdp_remote, PJ_EINVAL); 
    16701425 
    1671     m_rem = sdp_remote->media[media_index]; 
    1672     m_loc = sdp_local->media[media_index]; 
    1673  
    1674     if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP) == 0) 
    1675         srtp->peer_use = PJMEDIA_SRTP_MANDATORY; 
    1676     else 
    1677         srtp->peer_use = PJMEDIA_SRTP_OPTIONAL; 
    1678  
    1679     /* For answerer side, this function will just have to start SRTP */ 
    1680  
    1681     /* Check remote media transport & set local media transport 
    1682      * based on SRTP usage option. 
     1426    status = pjmedia_transport_media_start(srtp->member_tp, pool, 
     1427                                           sdp_local, sdp_remote, 
     1428                                           media_index); 
     1429    if (status != PJ_SUCCESS || srtp->bypass_srtp) 
     1430        return status; 
     1431 
     1432    /* Invoke media_start() of all keying methods */ 
     1433    for (i=0; i < srtp->keying_cnt; ) { 
     1434        status = pjmedia_transport_media_start(srtp->keying[i], pool, 
     1435                                               sdp_local, sdp_remote, 
     1436                                               media_index); 
     1437        if (status != PJ_SUCCESS) { 
     1438            /* This keying method returns error, remove it */ 
     1439            pj_array_erase(srtp->keying, sizeof(srtp->keying[0]), 
     1440                           srtp->keying_cnt, i); 
     1441            srtp->keying_cnt--; 
     1442            last_err_st = status; 
     1443            continue; 
     1444        } 
     1445 
     1446        if (!srtp_crypto_empty(&srtp->tx_policy_neg) && 
     1447            !srtp_crypto_empty(&srtp->rx_policy_neg)) 
     1448        { 
     1449            /* SRTP nego is done, let's destroy any other keying. */ 
     1450            unsigned j; 
     1451            for (j = 0; j < srtp->keying_cnt; ++j) { 
     1452                if (j != i) 
     1453                    pjmedia_transport_close(srtp->keying[j]); 
     1454            } 
     1455            srtp->keying_cnt = 1; 
     1456            srtp->keying[0] = srtp->keying[i]; 
     1457            srtp->keying_pending_cnt = 0; 
     1458            break; 
     1459        } 
     1460 
     1461        i++; 
     1462    } 
     1463 
     1464    /* All keying method failed to process remote SDP? */ 
     1465    if (srtp->keying_cnt == 0) 
     1466        return last_err_st; 
     1467 
     1468    /* If SRTP key is being negotiated, just return now. 
     1469     * The keying method should start the SRTP once keying nego is done. 
    16831470     */ 
    1684     if (srtp->offerer_side) { 
    1685         if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 
    1686             if (pjmedia_sdp_media_find_attr(m_rem, &ID_CRYPTO, NULL)) { 
    1687                 DEACTIVATE_MEDIA(pool, m_loc); 
    1688                 return PJMEDIA_SRTP_ESDPINCRYPTO; 
    1689             } 
    1690             goto BYPASS_SRTP; 
    1691         } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) { 
    1692             // Regardless the answer's transport type (RTP/AVP or RTP/SAVP), 
    1693             // the answer must be processed through in optional mode. 
    1694             // Please note that at this point transport type is ensured to be 
    1695             // RTP/AVP or RTP/SAVP, see transport_media_create() 
    1696             //if (pj_stricmp(&m_rem->desc.transport, &m_loc->desc.transport)) { 
    1697                 //DEACTIVATE_MEDIA(pool, m_loc); 
    1698                 //return PJMEDIA_SDP_EINPROTO; 
    1699             //} 
    1700             fill_local_crypto(srtp->pool, m_loc, loc_crypto, &loc_cryto_cnt); 
    1701         } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 
    1702             if (pj_stricmp(&m_rem->desc.transport, &ID_RTP_SAVP)) { 
    1703                 DEACTIVATE_MEDIA(pool, m_loc); 
    1704                 return PJMEDIA_SDP_EINPROTO; 
    1705             } 
    1706             fill_local_crypto(srtp->pool, m_loc, loc_crypto, &loc_cryto_cnt); 
    1707         } 
    1708     } 
    1709  
    1710     if (srtp->offerer_side) { 
    1711         /* find supported crypto-suite, get the tag, and assign policy_local */ 
    1712         pjmedia_srtp_crypto tmp_tx_crypto; 
    1713         pj_bool_t has_crypto_attr = PJ_FALSE; 
    1714         int rem_tag; 
    1715         int j; 
    1716  
    1717         for (i=0; i<m_rem->attr_count; ++i) { 
    1718             if (pj_stricmp(&m_rem->attr[i]->name, &ID_CRYPTO) != 0) 
    1719                 continue; 
    1720  
    1721             /* more than one crypto attribute in media answer */ 
    1722             if (has_crypto_attr) { 
    1723                 DEACTIVATE_MEDIA(pool, m_loc); 
    1724                 return PJMEDIA_SRTP_ESDPAMBIGUEANS; 
    1725             } 
    1726  
    1727             has_crypto_attr = PJ_TRUE; 
    1728  
    1729             status = parse_attr_crypto(srtp->pool, m_rem->attr[i], 
    1730                                        &tmp_tx_crypto, &rem_tag); 
    1731             if (status != PJ_SUCCESS) 
    1732                 return status; 
    1733  
    1734  
    1735             /* Tag range check, our tags in the offer must be in the SRTP  
    1736              * setting range, so does the remote answer's. The remote answer's  
    1737              * tag must not exceed the tag range of the local offer. 
    1738              */ 
    1739             if (rem_tag < 1 || rem_tag > (int)srtp->setting.crypto_count || 
    1740                 rem_tag > loc_cryto_cnt)  
    1741              
    1742             { 
    1743                 DEACTIVATE_MEDIA(pool, m_loc); 
    1744                 return PJMEDIA_SRTP_ESDPINCRYPTOTAG; 
    1745             } 
    1746  
    1747             /* match the crypto name */ 
    1748             if (pj_stricmp(&tmp_tx_crypto.name,  
    1749                            &loc_crypto[rem_tag-1].name) != 0)            
    1750             { 
    1751                 DEACTIVATE_MEDIA(pool, m_loc); 
    1752                 return PJMEDIA_SRTP_ECRYPTONOTMATCH; 
    1753             } 
    1754  
    1755             /* Find the crypto from the setting. */ 
    1756             for (j = 0; j < (int)srtp->setting.crypto_count; ++j) { 
    1757                 if (pj_stricmp(&tmp_tx_crypto.name,  
    1758                                &srtp->setting.crypto[j].name) == 0)  
    1759                  
    1760                 { 
    1761                     srtp->tx_policy_neg = srtp->setting.crypto[j]; 
    1762                     break; 
    1763                 }                
    1764             } 
    1765              
    1766             srtp->rx_policy_neg = tmp_tx_crypto; 
    1767         } 
    1768  
    1769         if (srtp->setting.use == PJMEDIA_SRTP_DISABLED) { 
    1770             /* should never reach here */ 
    1771             goto BYPASS_SRTP; 
    1772         } else if (srtp->setting.use == PJMEDIA_SRTP_OPTIONAL) { 
    1773             if (!has_crypto_attr) 
    1774                 goto BYPASS_SRTP; 
    1775         } else if (srtp->setting.use == PJMEDIA_SRTP_MANDATORY) { 
    1776             if (!has_crypto_attr) { 
    1777                 DEACTIVATE_MEDIA(pool, m_loc); 
    1778                 return PJMEDIA_SRTP_ESDPREQCRYPTO; 
    1779             } 
    1780         } 
    1781  
    1782         /* At this point, we get valid rx_policy_neg & tx_policy_neg. */ 
    1783     } 
    1784  
    1785     /* Make sure we have the SRTP policies */ 
    1786     if (srtp_crypto_empty(&srtp->tx_policy_neg) || 
    1787         srtp_crypto_empty(&srtp->rx_policy_neg)) 
    1788     { 
    1789         goto BYPASS_SRTP; 
    1790     } 
    1791  
    1792     /* Reset probation counts */ 
    1793     srtp->probation_cnt = PROBATION_CNT_INIT; 
    1794  
    1795     /* Got policy_local & policy_remote, let's initalize the SRTP */ 
    1796  
    1797     /* Ticket #1075: media_start() is called whenever media description 
    1798      * gets updated, e.g: call hold, however we should restart SRTP only 
    1799      * when the SRTP policy settings are updated. 
    1800      */ 
    1801     if (srtp_crypto_cmp(&srtp->tx_policy_neg, &srtp->tx_policy) || 
    1802         srtp_crypto_cmp(&srtp->rx_policy_neg, &srtp->rx_policy)) 
    1803     { 
    1804         status = pjmedia_transport_srtp_start(tp, 
    1805                                               &srtp->tx_policy_neg, 
    1806                                               &srtp->rx_policy_neg); 
    1807         if (status != PJ_SUCCESS) 
    1808             return status; 
    1809     } 
    1810  
    1811     srtp->bypass_srtp = PJ_FALSE; 
    1812  
    1813     goto PROPAGATE_MEDIA_START; 
    1814  
    1815 BYPASS_SRTP: 
    1816     srtp->bypass_srtp = PJ_TRUE; 
    1817     srtp->peer_use = PJMEDIA_SRTP_DISABLED; 
    1818     if (srtp->session_inited) { 
    1819         pjmedia_transport_srtp_stop(tp); 
    1820     } 
    1821  
    1822 PROPAGATE_MEDIA_START: 
    1823     return pjmedia_transport_media_start(srtp->member_tp, pool, 
    1824                                          sdp_local, sdp_remote, 
    1825                                          media_index); 
    1826 } 
     1471    if (srtp->keying_pending_cnt) 
     1472        return PJ_SUCCESS; 
     1473 
     1474    /* Start SRTP */ 
     1475    status = start_srtp(srtp); 
     1476 
     1477    return status; 
     1478} 
     1479 
    18271480 
    18281481static pj_status_t transport_media_stop(pjmedia_transport *tp) 
     
    18301483    struct transport_srtp *srtp = (struct transport_srtp*) tp; 
    18311484    pj_status_t status; 
     1485    unsigned i; 
    18321486 
    18331487    PJ_ASSERT_RETURN(tp, PJ_EINVAL); 
    18341488 
     1489    /* Invoke media_stop() of all keying methods */ 
     1490    for (i=0; i < srtp->keying_cnt; ++i) { 
     1491        pjmedia_transport_media_stop(srtp->keying[i]); 
     1492    } 
     1493 
     1494    /* Invoke media_stop() of member tp */ 
    18351495    status = pjmedia_transport_media_stop(srtp->member_tp); 
    18361496    if (status != PJ_SUCCESS) 
     
    18381498                   "SRTP failed stop underlying media transport.")); 
    18391499 
     1500    /* Finally, stop SRTP */ 
    18401501    return pjmedia_transport_srtp_stop(tp); 
    18411502} 
     1503 
    18421504 
    18431505/* Utility */ 
Note: See TracChangeset for help on using the changeset viewer.