Changeset 5621


Ignore:
Timestamp:
Jul 5, 2017 5:37:24 AM (7 years ago)
Author:
nanang
Message:

Re #2018: Added API pjmedia_transport_srtp_dtls_start_nego() to start DTLS-SRTP nego without SDP offer/answer.

Location:
pjproject/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/transport_srtp.h

    r5597 r5621  
    269269 
    270270/** 
     271 * This structure specifies DTLS-SRTP negotiation parameters. 
     272 */ 
     273typedef struct pjmedia_srtp_dtls_nego_param 
     274{ 
     275    /** 
     276     * Fingerprint of remote certificate, should be formatted as 
     277     * "SHA-256/1 XX:XX:XX...". If this is not set, fingerprint verification 
     278     * will not be performed. 
     279     */ 
     280    pj_str_t             rem_fingerprint; 
     281 
     282    /** 
     283     * Remote address and port. 
     284     */ 
     285    pj_sockaddr          rem_addr; 
     286 
     287    /** 
     288     * Remote RTCP address and port. 
     289     */ 
     290    pj_sockaddr          rem_rtcp; 
     291 
     292    /** 
     293     * Set to PJ_TRUE if our role is active. Active role will initiates 
     294     * the DTLS negotiation. Passive role will wait for incoming DTLS 
     295     * negotiation packet. 
     296     */ 
     297    pj_bool_t            is_role_active; 
     298 
     299} pjmedia_srtp_dtls_nego_param; 
     300 
     301 
     302 
     303/** 
    271304 * Initialize SRTP library. This function should be called before 
    272305 * any SRTP functions, however calling #pjmedia_transport_srtp_create()  
     
    308341                                       const pjmedia_srtp_setting *opt, 
    309342                                       pjmedia_transport **p_tp); 
     343 
     344/** 
     345 * Get fingerprint of local DTLS-SRTP certificate. 
     346 * 
     347 * @param srtp      The SRTP transport. 
     348 * @param hash      Fingerprint hash algorithm, currently valid values are 
     349 *                  "SHA-256" and "SHA-1". 
     350 * @param buf       Buffer for fingerprint output. The output will be 
     351 *                  formatted as "SHA-256/1 XX:XX:XX..." and null terminated. 
     352 * @param len       On input, the size of the buffer. 
     353 *                  On output, the length of the fingerprint. 
     354 * 
     355 * @return          PJ_SUCCESS on success. 
     356 */ 
     357PJ_DECL(pj_status_t) pjmedia_transport_srtp_dtls_get_fingerprint( 
     358                                pjmedia_transport *srtp, 
     359                                const char *hash, 
     360                                char *buf, pj_size_t *len); 
     361 
     362 
     363/** 
     364 * Manually start DTLS-SRTP negotiation with the given parameters. Application 
     365 * only needs to call this function when the SRTP transport is used without 
     366 * SDP offer/answer. When SDP offer/answer framework is used, the DTLS-SRTP 
     367 * negotiation will be handled by pjmedia_transport_media_create(), 
     368 * pjmedia_transport_media_start(), pjmedia_transport_media_encode_sdp(), and 
     369 * pjmedia_transport_media_stop(). 
     370 * 
     371 * When the negotiation completes, application will be notified via SRTP 
     372 * callback on_srtp_nego_complete(), if set. If the negotiation is successful, 
     373 * SRTP will be automatically started. 
     374 * 
     375 * Note that if the SRTP member transport is an ICE transport, application 
     376 * should only call this function after ICE negotiation is completed 
     377 * successfully. 
     378 * 
     379 * @param srtp      The SRTP transport. 
     380 * @param param     DTLS-SRTP nego parameter. 
     381 * 
     382 * @return          PJ_SUCCESS on success. 
     383 */ 
     384PJ_DECL(pj_status_t) pjmedia_transport_srtp_dtls_start_nego( 
     385                                pjmedia_transport *srtp, 
     386                                const pjmedia_srtp_dtls_nego_param *param); 
    310387 
    311388 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_srtp.c

    r5614 r5621  
    403403#if defined(PJMEDIA_SRTP_HAS_DTLS) && (PJMEDIA_SRTP_HAS_DTLS != 0) 
    404404#  include "transport_srtp_dtls.c" 
     405#else 
     406PJ_DEF(pj_status_t) pjmedia_transport_srtp_dtls_start_nego( 
     407                                pjmedia_transport *srtp, 
     408                                const pjmedia_srtp_dtls_nego_param *param) 
     409{ 
     410    PJ_UNUSED_ARG(srtp); 
     411    PJ_UNUSED_ARG(param); 
     412    return PJ_ENOTSUP; 
     413} 
     414PJ_DEF(pj_status_t) pjmedia_transport_srtp_dtls_get_fingerprint( 
     415                                pjmedia_transport *srtp, 
     416                                const char *hash, 
     417                                char *buf, pj_size_t *len) 
     418{ 
     419    PJ_UNUSED_ARG(srtp); 
     420    PJ_UNUSED_ARG(hash); 
     421    PJ_UNUSED_ARG(buf); 
     422    PJ_UNUSED_ARG(len); 
     423    return PJ_ENOTSUP; 
     424} 
    405425#endif 
    406426 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_srtp_dtls.c

    r5614 r5621  
    188188 
    189189    *p_keying = &ds->base; 
    190     PJ_LOG(5,(THIS_FILE, "SRTP keying DTLS-SRTP created")); 
     190    PJ_LOG(5,(srtp->pool->obj_name, "SRTP keying DTLS-SRTP created")); 
    191191    return PJ_SUCCESS; 
    192192} 
     
    549549        is_sha256 = PJ_FALSE; 
    550550    else { 
    551         PJ_LOG(4,(ds->base.name, "Remote hash algo in SDP for " 
    552                   "DTLS-SRTP is not supported")); 
     551        PJ_LOG(4,(ds->base.name, "Hash algo specified in remote SDP for " 
     552                  "its DTLS certificate fingerprint is not supported")); 
    553553        return PJ_ENOTSUP; 
    554554    } 
     
    641641        ds->srtp->keying_pending_cnt--; 
    642642 
     643        /* Copy negotiated policy to SRTP */ 
    643644        ds->srtp->tx_policy_neg = ds->tx_crypto; 
    644645        ds->srtp->rx_policy_neg = ds->rx_crypto; 
     646 
    645647        status = start_srtp(ds->srtp); 
    646648        if (status != PJ_SUCCESS) 
     
    716718    /* Finally, DTLS nego started! */ 
    717719    ds->nego_started = PJ_TRUE; 
    718     PJ_LOG(2,(ds->base.name, "DTLS-SRTP negotiation initiated as %s", 
     720    PJ_LOG(4,(ds->base.name, "DTLS-SRTP negotiation initiated as %s", 
    719721              (ds->setup==DTLS_SETUP_ACTIVE? "client":"server"))); 
    720722 
     
    12481250        ds->srtp->rx_policy_neg = ds->rx_crypto; 
    12491251 
    1250         /* Verify remote fingerprint if not yet */ 
     1252        /* Verify remote fingerprint (if available) */ 
    12511253        if (ds->rem_fingerprint.slen && ds->rem_fprint_status == PJ_EPENDING) 
     1254        { 
    12521255            ds->rem_fprint_status = ssl_match_fingerprint(ds); 
    1253         if (ds->rem_fprint_status != PJ_SUCCESS) { 
    1254             pj_perror(4, ds->base.name, ds->rem_fprint_status, 
    1255                       "Fingerprint specified in remote SDP doesn't match " 
    1256                       "to actual remote certificate fingerprint!"); 
    1257             return ds->rem_fprint_status; 
     1256            if (ds->rem_fprint_status != PJ_SUCCESS) { 
     1257                pj_perror(4, ds->base.name, ds->rem_fprint_status, 
     1258                          "Fingerprint specified in remote SDP doesn't match " 
     1259                          "to actual remote certificate fingerprint!"); 
     1260                return ds->rem_fprint_status; 
     1261            } 
    12581262        } 
    12591263 
     
    13451349    return PJ_SUCCESS; 
    13461350} 
     1351 
     1352 
     1353/* Get fingerprint of local DTLS-SRTP certificate. */ 
     1354PJ_DEF(pj_status_t) pjmedia_transport_srtp_dtls_get_fingerprint( 
     1355                                pjmedia_transport *tp, 
     1356                                const char *hash, 
     1357                                char *buf, pj_size_t *len) 
     1358{ 
     1359    PJ_ASSERT_RETURN(dtls_cert, PJ_EINVALIDOP); 
     1360    PJ_ASSERT_RETURN(tp && hash && buf && len, PJ_EINVAL); 
     1361    PJ_ASSERT_RETURN(pj_ansi_strcmp(hash, "SHA-256")==0 || 
     1362                     pj_ansi_strcmp(hash, "SHA-1")==0, PJ_EINVAL); 
     1363    PJ_UNUSED_ARG(tp); 
     1364 
     1365    return ssl_get_fingerprint(dtls_cert, 
     1366                               pj_ansi_strcmp(hash, "SHA-256")==0, 
     1367                               buf, len); 
     1368} 
     1369 
     1370 
     1371/* Manually start DTLS-SRTP negotiation (without SDP offer/answer) */ 
     1372PJ_DEF(pj_status_t) pjmedia_transport_srtp_dtls_start_nego( 
     1373                                pjmedia_transport *tp, 
     1374                                const pjmedia_srtp_dtls_nego_param *param) 
     1375{ 
     1376    transport_srtp *srtp = (transport_srtp*)tp; 
     1377    dtls_srtp *ds = NULL; 
     1378    unsigned j; 
     1379    pjmedia_transport_attach_param ap; 
     1380    pj_status_t status; 
     1381 
     1382    PJ_ASSERT_RETURN(tp && param, PJ_EINVAL); 
     1383    PJ_ASSERT_RETURN(pj_sockaddr_has_addr(&param->rem_addr), PJ_EINVAL); 
     1384 
     1385    /* Find DTLS keying and destroy any other keying. */ 
     1386    for (j = 0; j < srtp->keying_cnt; ++j) { 
     1387        if (srtp->keying[j]->op == &dtls_op) 
     1388            ds = (dtls_srtp*)srtp->keying[j]; 
     1389        else 
     1390            pjmedia_transport_close(srtp->keying[j]); 
     1391    } 
     1392 
     1393    /* DTLS-SRTP is not enabled */ 
     1394    if (!ds) 
     1395        return PJ_ENOTSUP; 
     1396 
     1397    /* Set SRTP keying to DTLS-SRTP only */ 
     1398    srtp->keying_cnt = 1; 
     1399    srtp->keying[0] = &ds->base; 
     1400    srtp->keying_pending_cnt = 1; 
     1401 
     1402    /* Apply param to DTLS-SRTP internal states */ 
     1403    pj_strdup(ds->pool, &ds->rem_fingerprint, &param->rem_fingerprint); 
     1404    ds->rem_fprint_status = PJ_EPENDING; 
     1405    ds->rem_addr = param->rem_addr; 
     1406    ds->rem_rtcp = param->rem_rtcp; 
     1407    ds->setup = param->is_role_active? DTLS_SETUP_ACTIVE:DTLS_SETUP_PASSIVE; 
     1408 
     1409    /* Pending start SRTP */ 
     1410    ds->pending_start = PJ_TRUE; 
     1411    srtp->keying_pending_cnt++; 
     1412 
     1413    /* Create SSL */ 
     1414    status = ssl_create(ds); 
     1415    if (status != PJ_SUCCESS) 
     1416        goto on_return; 
     1417 
     1418    /* Attach member transport, so we can send/receive DTLS init packets */ 
     1419    pj_bzero(&ap, sizeof(ap)); 
     1420    pj_sockaddr_cp(&ap.rem_addr, &ds->rem_addr); 
     1421    pj_sockaddr_cp(&ap.rem_rtcp, &ds->rem_rtcp); 
     1422    ap.addr_len = pj_sockaddr_get_len(&ap.rem_addr); 
     1423    status = pjmedia_transport_attach2(&ds->srtp->base, &ap); 
     1424    if (status != PJ_SUCCESS) 
     1425        goto on_return; 
     1426 
     1427    /* Start DTLS handshake */ 
     1428    pj_bzero(&srtp->rx_policy_neg, sizeof(srtp->rx_policy_neg)); 
     1429    pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg)); 
     1430    status = ssl_handshake(ds); 
     1431    if (status != PJ_SUCCESS) 
     1432        goto on_return; 
     1433 
     1434on_return: 
     1435    if (status != PJ_SUCCESS) { 
     1436        ssl_destroy(ds); 
     1437    } 
     1438    return status; 
     1439} 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_srtp_sdes.c

    r5617 r5621  
    7777 
    7878    sdes = PJ_POOL_ZALLOC_T(srtp->pool, pjmedia_transport); 
    79     pj_ansi_strncpy(sdes->name, "SDES", PJ_MAX_OBJ_NAME); 
     79    pj_ansi_strncpy(sdes->name, srtp->pool->obj_name, PJ_MAX_OBJ_NAME); 
     80    pj_memcpy(sdes->name, "sdes", 4); 
    8081    sdes->type = PJMEDIA_TRANSPORT_TYPE_SRTP; 
    8182    sdes->op = &sdes_op; 
     
    8384 
    8485    *p_keying = sdes; 
    85     PJ_LOG(5,(THIS_FILE, "SRTP keying SDES created")); 
     86    PJ_LOG(5,(srtp->pool->obj_name, "SRTP keying SDES created")); 
    8687    return PJ_SUCCESS; 
    8788} 
  • pjproject/trunk/pjsip-apps/src/samples/streamutil.c

    r5618 r5621  
    8888 "                             AES_CM_128_HMAC_SHA1_32                  \n" 
    8989 "                        Use this option along with the TX & RX keys,  \n" 
    90  "                        formated of 60 hex digits (e.g: E148DA..)      \n" 
     90 "                        formated of 60 hex digits (e.g: E148DA..)     \n" 
    9191 "  --srtp-tx-key         SRTP key for transmiting                      \n" 
    9292 "  --srtp-rx-key         SRTP key for receiving                        \n" 
     93 "  --srtp-dtls-client    Use DTLS for SRTP keying, as DTLS client      \n" 
     94 "  --srtp-dtls-server    Use DTLS for SRTP keying, as DTLS server      \n" 
    9395#endif 
    9496 
     
    147149                                  const pj_str_t *srtp_tx_key, 
    148150                                  const pj_str_t *srtp_rx_key, 
     151                                  pj_bool_t is_dtls_client, 
     152                                  pj_bool_t is_dtls_server, 
    149153#endif 
    150154                                  pjmedia_stream **p_stream ) 
     
    287291    /* Check if SRTP enabled */ 
    288292    if (use_srtp) { 
    289         pjmedia_srtp_crypto tx_plc, rx_plc; 
    290  
    291293        status = pjmedia_transport_srtp_create(med_endpt, transport,  
    292294                                               NULL, &srtp_tp); 
     
    294296            return status; 
    295297 
    296         pj_bzero(&tx_plc, sizeof(pjmedia_srtp_crypto)); 
    297         pj_bzero(&rx_plc, sizeof(pjmedia_srtp_crypto)); 
    298  
    299         tx_plc.key = *srtp_tx_key; 
    300         tx_plc.name = *crypto_suite; 
    301         rx_plc.key = *srtp_rx_key; 
    302         rx_plc.name = *crypto_suite; 
    303          
    304         status = pjmedia_transport_srtp_start(srtp_tp, &tx_plc, &rx_plc); 
    305         if (status != PJ_SUCCESS) 
    306             return status; 
     298        if (is_dtls_client || is_dtls_server) { 
     299            char fp[128]; 
     300            pj_size_t fp_len = sizeof(fp); 
     301            pjmedia_srtp_dtls_nego_param dtls_param; 
     302             
     303            pjmedia_transport_srtp_dtls_get_fingerprint(srtp_tp, "SHA-256", fp, &fp_len); 
     304            PJ_LOG(3, (THIS_FILE, "Local cert fingerprint: %s", fp)); 
     305 
     306            pj_bzero(&dtls_param, sizeof(dtls_param)); 
     307            pj_sockaddr_cp(&dtls_param.rem_addr, rem_addr); 
     308            pj_sockaddr_cp(&dtls_param.rem_rtcp, rem_addr); 
     309            dtls_param.is_role_active = is_dtls_client; 
     310 
     311            status = pjmedia_transport_srtp_dtls_start_nego(srtp_tp, &dtls_param); 
     312            if (status != PJ_SUCCESS) 
     313                return status; 
     314        } else { 
     315            pjmedia_srtp_crypto tx_plc, rx_plc; 
     316 
     317            pj_bzero(&tx_plc, sizeof(pjmedia_srtp_crypto)); 
     318            pj_bzero(&rx_plc, sizeof(pjmedia_srtp_crypto)); 
     319 
     320            tx_plc.key = *srtp_tx_key; 
     321            tx_plc.name = *crypto_suite; 
     322            rx_plc.key = *srtp_rx_key; 
     323            rx_plc.name = *crypto_suite; 
     324         
     325            status = pjmedia_transport_srtp_start(srtp_tp, &tx_plc, &rx_plc); 
     326            if (status != PJ_SUCCESS) 
     327                return status; 
     328        } 
    307329 
    308330        transport = srtp_tp; 
     
    362384    pj_str_t  srtp_rx_key = {NULL, 0}; 
    363385    pj_str_t  srtp_crypto_suite = {NULL, 0}; 
     386    pj_bool_t is_dtls_client = PJ_FALSE; 
     387    pj_bool_t is_dtls_server = PJ_FALSE; 
    364388    int tmp_key_len; 
    365389#endif 
     
    392416        OPT_SRTP_TX_KEY = 'x', 
    393417        OPT_SRTP_RX_KEY = 'y', 
     418        OPT_SRTP_DTLS_CLIENT = 'd', 
     419        OPT_SRTP_DTLS_SERVER = 'D', 
    394420        OPT_HELP        = 'h', 
    395421    }; 
     
    409435        { "srtp-tx-key",    1, 0, OPT_SRTP_TX_KEY }, 
    410436        { "srtp-rx-key",    1, 0, OPT_SRTP_RX_KEY }, 
     437        { "srtp-dtls-client", 0, 0, OPT_SRTP_DTLS_CLIENT }, 
     438        { "srtp-dtls-server", 0, 0, OPT_SRTP_DTLS_SERVER }, 
    411439#endif 
    412440        { "help",           0, 0, OPT_HELP }, 
     
    510538            pj_strset(&srtp_rx_key, tmp_rx_key, tmp_key_len/2); 
    511539            break; 
     540        case OPT_SRTP_DTLS_CLIENT: 
     541            is_dtls_client = PJ_TRUE; 
     542            if (is_dtls_server) { 
     543                printf("Error: Cannot be as both DTLS server & client\n"); 
     544                return 1; 
     545            } 
     546            break; 
     547        case OPT_SRTP_DTLS_SERVER: 
     548            is_dtls_server = PJ_TRUE; 
     549            if (is_dtls_client) { 
     550                printf("Error: Cannot be as both DTLS server & client\n"); 
     551                return 1; 
     552            } 
     553            break; 
    512554#endif 
    513555 
     
    525567 
    526568    /* Verify arguments. */ 
    527     if (dir & PJMEDIA_DIR_ENCODING) { 
     569    if (dir & PJMEDIA_DIR_ENCODING || is_dtls_client || is_dtls_server) { 
    528570        if (remote_addr.sin_addr.s_addr == 0) { 
    529571            printf("Error: remote address must be set\n"); 
     
    540582    /* SRTP validation */ 
    541583    if (use_srtp) { 
    542         if (!srtp_tx_key.slen || !srtp_rx_key.slen) 
     584        if (!is_dtls_client && !is_dtls_server &&  
     585            (!srtp_tx_key.slen || !srtp_rx_key.slen)) 
    543586        { 
    544587            printf("Error: Key for each SRTP stream direction must be set\n"); 
     
    596639                           use_srtp, &srtp_crypto_suite,  
    597640                           &srtp_tx_key, &srtp_rx_key, 
     641                           is_dtls_client, is_dtls_server, 
    598642#endif 
    599643                           &stream); 
Note: See TracChangeset for help on using the changeset viewer.