Sun Oct 16 2011 08:41:46

Asterisk developer's documentation


res_srtp.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2005, Mikael Magnusson
00005  *
00006  * Mikael Magnusson <mikma@users.sourceforge.net>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  *
00018  * Builds on libSRTP http://srtp.sourceforge.net
00019  */
00020 
00021 /*! \file res_srtp.c
00022  *
00023  * \brief Secure RTP (SRTP)
00024  *
00025  * Secure RTP (SRTP)
00026  * Specified in RFC 3711.
00027  *
00028  * \author Mikael Magnusson <mikma@users.sourceforge.net>
00029  */
00030 
00031 /*** MODULEINFO
00032    <depend>srtp</depend>
00033    <support_level>core</support_level>
00034 ***/
00035 
00036 /* See https://wiki.asterisk.org/wiki/display/AST/Secure+Calling */
00037 
00038 #include "asterisk.h"
00039 
00040 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00041 
00042 #include <srtp/srtp.h>
00043 
00044 #include "asterisk/lock.h"
00045 #include "asterisk/sched.h"
00046 #include "asterisk/module.h"
00047 #include "asterisk/options.h"
00048 #include "asterisk/rtp_engine.h"
00049 #include "asterisk/astobj2.h"
00050 
00051 struct ast_srtp {
00052    struct ast_rtp_instance *rtp;
00053    struct ao2_container *policies;
00054    srtp_t session;
00055    const struct ast_srtp_cb *cb;
00056    void *data;
00057    unsigned char buf[8192 + AST_FRIENDLY_OFFSET];
00058 };
00059 
00060 struct ast_srtp_policy {
00061    srtp_policy_t sp;
00062 };
00063 
00064 static int g_initialized = 0;
00065 
00066 /* SRTP functions */
00067 static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy);
00068 static void ast_srtp_destroy(struct ast_srtp *srtp);
00069 static int ast_srtp_add_stream(struct ast_srtp *srtp, struct ast_srtp_policy *policy);
00070 static int ast_srtp_change_source(struct ast_srtp *srtp, unsigned int from_ssrc, unsigned int to_ssrc);
00071 
00072 static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rtcp);
00073 static int ast_srtp_protect(struct ast_srtp *srtp, void **buf, int *len, int rtcp);
00074 static void ast_srtp_set_cb(struct ast_srtp *srtp, const struct ast_srtp_cb *cb, void *data);
00075 static int ast_srtp_get_random(unsigned char *key, size_t len);
00076 
00077 /* Policy functions */
00078 static struct ast_srtp_policy *ast_srtp_policy_alloc(void);
00079 static void ast_srtp_policy_destroy(struct ast_srtp_policy *policy);
00080 static int ast_srtp_policy_set_suite(struct ast_srtp_policy *policy, enum ast_srtp_suite suite);
00081 static int ast_srtp_policy_set_master_key(struct ast_srtp_policy *policy, const unsigned char *key, size_t key_len, const unsigned char *salt, size_t salt_len);
00082 static void ast_srtp_policy_set_ssrc(struct ast_srtp_policy *policy, unsigned long ssrc, int inbound);
00083 
00084 static struct ast_srtp_res srtp_res = {
00085    .create = ast_srtp_create,
00086    .destroy = ast_srtp_destroy,
00087    .add_stream = ast_srtp_add_stream,
00088    .change_source = ast_srtp_change_source,
00089    .set_cb = ast_srtp_set_cb,
00090    .unprotect = ast_srtp_unprotect,
00091    .protect = ast_srtp_protect,
00092    .get_random = ast_srtp_get_random
00093 };
00094 
00095 static struct ast_srtp_policy_res policy_res = {
00096    .alloc = ast_srtp_policy_alloc,
00097    .destroy = ast_srtp_policy_destroy,
00098    .set_suite = ast_srtp_policy_set_suite,
00099    .set_master_key = ast_srtp_policy_set_master_key,
00100    .set_ssrc = ast_srtp_policy_set_ssrc
00101 };
00102 
00103 static const char *srtp_errstr(int err)
00104 {
00105    switch(err) {
00106    case err_status_ok:
00107       return "nothing to report";
00108    case err_status_fail:
00109       return "unspecified failure";
00110    case err_status_bad_param:
00111       return "unsupported parameter";
00112    case err_status_alloc_fail:
00113       return "couldn't allocate memory";
00114    case err_status_dealloc_fail:
00115       return "couldn't deallocate properly";
00116    case err_status_init_fail:
00117       return "couldn't initialize";
00118    case err_status_terminus:
00119       return "can't process as much data as requested";
00120    case err_status_auth_fail:
00121       return "authentication failure";
00122    case err_status_cipher_fail:
00123       return "cipher failure";
00124    case err_status_replay_fail:
00125       return "replay check failed (bad index)";
00126    case err_status_replay_old:
00127       return "replay check failed (index too old)";
00128    case err_status_algo_fail:
00129       return "algorithm failed test routine";
00130    case err_status_no_such_op:
00131       return "unsupported operation";
00132    case err_status_no_ctx:
00133       return "no appropriate context found";
00134    case err_status_cant_check:
00135       return "unable to perform desired validation";
00136    case err_status_key_expired:
00137       return "can't use key any more";
00138    default:
00139       return "unknown";
00140    }
00141 }
00142 
00143 static int policy_hash_fn(const void *obj, const int flags)
00144 {
00145    const struct ast_srtp_policy *policy = obj;
00146 
00147    return policy->sp.ssrc.type == ssrc_specific ? policy->sp.ssrc.value : policy->sp.ssrc.type;
00148 }
00149 
00150 static int policy_cmp_fn(void *obj, void *arg, int flags)
00151 {
00152    const struct ast_srtp_policy *one = obj, *two = arg;
00153 
00154    return one->sp.ssrc.type == two->sp.ssrc.type && one->sp.ssrc.value == two->sp.ssrc.value;
00155 }
00156 
00157 static struct ast_srtp_policy *find_policy(struct ast_srtp *srtp, const srtp_policy_t *policy, int flags)
00158 {
00159    struct ast_srtp_policy tmp = {
00160       .sp = {
00161          .ssrc.type = policy->ssrc.type,
00162          .ssrc.value = policy->ssrc.value,
00163       },
00164    };
00165 
00166    return ao2_t_find(srtp->policies, &tmp, flags, "Looking for policy");
00167 }
00168 
00169 static struct ast_srtp *res_srtp_new(void)
00170 {
00171    struct ast_srtp *srtp;
00172 
00173    if (!(srtp = ast_calloc(1, sizeof(*srtp)))) {
00174       ast_log(LOG_ERROR, "Unable to allocate memory for srtp\n");
00175       return NULL;
00176    }
00177 
00178    if (!(srtp->policies = ao2_t_container_alloc(5, policy_hash_fn, policy_cmp_fn, "SRTP policy container"))) {
00179       ast_free(srtp);
00180       return NULL;
00181    }
00182 
00183    return srtp;
00184 }
00185 
00186 /*
00187   struct ast_srtp_policy
00188 */
00189 static void srtp_event_cb(srtp_event_data_t *data)
00190 {
00191    switch (data->event) {
00192    case event_ssrc_collision:
00193       ast_debug(1, "SSRC collision\n");
00194       break;
00195    case event_key_soft_limit:
00196       ast_debug(1, "event_key_soft_limit\n");
00197       break;
00198    case event_key_hard_limit:
00199       ast_debug(1, "event_key_hard_limit\n");
00200       break;
00201    case event_packet_index_limit:
00202       ast_debug(1, "event_packet_index_limit\n");
00203       break;
00204    }
00205 }
00206 
00207 static void ast_srtp_policy_set_ssrc(struct ast_srtp_policy *policy,
00208       unsigned long ssrc, int inbound)
00209 {
00210    if (ssrc) {
00211       policy->sp.ssrc.type = ssrc_specific;
00212       policy->sp.ssrc.value = ssrc;
00213    } else {
00214       policy->sp.ssrc.type = inbound ? ssrc_any_inbound : ssrc_any_outbound;
00215    }
00216 }
00217 
00218 static void policy_destructor(void *obj)
00219 {
00220    struct ast_srtp_policy *policy = obj;
00221 
00222    if (policy->sp.key) {
00223       ast_free(policy->sp.key);
00224       policy->sp.key = NULL;
00225    }
00226 }
00227 
00228 static struct ast_srtp_policy *ast_srtp_policy_alloc()
00229 {
00230    struct ast_srtp_policy *tmp;
00231 
00232    if (!(tmp = ao2_t_alloc(sizeof(*tmp), policy_destructor, "Allocating policy"))) {
00233       ast_log(LOG_ERROR, "Unable to allocate memory for srtp_policy\n");
00234    }
00235 
00236    return tmp;
00237 }
00238 
00239 static void ast_srtp_policy_destroy(struct ast_srtp_policy *policy)
00240 {
00241    ao2_t_ref(policy, -1, "Destroying policy");
00242 }
00243 
00244 static int policy_set_suite(crypto_policy_t *p, enum ast_srtp_suite suite)
00245 {
00246    switch (suite) {
00247    case AST_AES_CM_128_HMAC_SHA1_80:
00248       p->cipher_type = AES_128_ICM;
00249       p->cipher_key_len = 30;
00250       p->auth_type = HMAC_SHA1;
00251       p->auth_key_len = 20;
00252       p->auth_tag_len = 10;
00253       p->sec_serv = sec_serv_conf_and_auth;
00254       return 0;
00255 
00256    case AST_AES_CM_128_HMAC_SHA1_32:
00257       p->cipher_type = AES_128_ICM;
00258       p->cipher_key_len = 30;
00259       p->auth_type = HMAC_SHA1;
00260       p->auth_key_len = 20;
00261       p->auth_tag_len = 4;
00262       p->sec_serv = sec_serv_conf_and_auth;
00263       return 0;
00264 
00265    default:
00266       ast_log(LOG_ERROR, "Invalid crypto suite: %d\n", suite);
00267       return -1;
00268    }
00269 }
00270 
00271 static int ast_srtp_policy_set_suite(struct ast_srtp_policy *policy, enum ast_srtp_suite suite)
00272 {
00273    return policy_set_suite(&policy->sp.rtp, suite) | policy_set_suite(&policy->sp.rtcp, suite);
00274 }
00275 
00276 static int ast_srtp_policy_set_master_key(struct ast_srtp_policy *policy, const unsigned char *key, size_t key_len, const unsigned char *salt, size_t salt_len)
00277 {
00278    size_t size = key_len + salt_len;
00279    unsigned char *master_key;
00280 
00281    if (policy->sp.key) {
00282       ast_free(policy->sp.key);
00283       policy->sp.key = NULL;
00284    }
00285 
00286    if (!(master_key = ast_calloc(1, size))) {
00287       return -1;
00288    }
00289 
00290    memcpy(master_key, key, key_len);
00291    memcpy(master_key + key_len, salt, salt_len);
00292 
00293    policy->sp.key = master_key;
00294 
00295    return 0;
00296 }
00297 
00298 static int ast_srtp_get_random(unsigned char *key, size_t len)
00299 {
00300    return crypto_get_random(key, len) != err_status_ok ? -1: 0;
00301 }
00302 
00303 static void ast_srtp_set_cb(struct ast_srtp *srtp, const struct ast_srtp_cb *cb, void *data)
00304 {
00305    if (!srtp) {
00306       return;
00307    }
00308 
00309    srtp->cb = cb;
00310    srtp->data = data;
00311 }
00312 
00313 /* Vtable functions */
00314 static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rtcp)
00315 {
00316    int res = 0;
00317    int i;
00318    int retry = 0;
00319    struct ast_rtp_instance_stats stats = {0,};
00320 
00321    tryagain:
00322 
00323    for (i = 0; i < 2; i++) {
00324       res = rtcp ? srtp_unprotect_rtcp(srtp->session, buf, len) : srtp_unprotect(srtp->session, buf, len);
00325       if (res != err_status_no_ctx) {
00326          break;
00327       }
00328 
00329       if (srtp->cb && srtp->cb->no_ctx) {
00330          if (ast_rtp_instance_get_stats(srtp->rtp, &stats, AST_RTP_INSTANCE_STAT_REMOTE_SSRC)) {
00331             break;
00332          }
00333          if (srtp->cb->no_ctx(srtp->rtp, stats.remote_ssrc, srtp->data) < 0) {
00334             break;
00335          }
00336       } else {
00337          break;
00338       }
00339    }
00340 
00341    if (retry == 0  && res == err_status_replay_old) {
00342       ast_log(LOG_WARNING, "SRTP unprotect: %s\n", srtp_errstr(res));
00343 
00344       if (srtp->session) {
00345          struct ast_srtp_policy *policy;
00346          struct ao2_iterator it;
00347          int policies_count = 0;
00348          
00349          // dealloc first
00350          ast_log(LOG_WARNING, "SRTP destroy before re-create\n");
00351          srtp_dealloc(srtp->session);
00352          
00353          // get the count
00354          policies_count = ao2_container_count(srtp->policies);
00355          
00356          // get the first to build up
00357          it = ao2_iterator_init(srtp->policies, 0);
00358          policy = ao2_iterator_next(&it);
00359 
00360          ast_log(LOG_WARNING, "SRTP try to re-create\n");
00361             if (srtp_create(&srtp->session, &policy->sp) == err_status_ok) {
00362             ast_log(LOG_WARNING, "SRTP re-created with first policy\n");
00363             
00364             // unref first element
00365             ao2_t_ref(policy, -1, "Unreffing first policy for re-creating srtp session");
00366             
00367             // if we have more than one policy, add them afterwards  
00368             if (policies_count > 1) {
00369                ast_log(LOG_WARNING, "Add all the other %d policies\n", policies_count-1);
00370                while ((policy = ao2_iterator_next(&it))) {
00371                   srtp_add_stream(srtp->session, &policy->sp);
00372                   ao2_t_ref(policy, -1, "Unreffing n-th policy for re-creating srtp session");
00373                }
00374             }
00375             
00376             retry++;
00377             ao2_iterator_destroy(&it);
00378             goto tryagain;
00379          }
00380          ao2_iterator_destroy(&it);
00381       }
00382    }
00383 
00384    if (res != err_status_ok && res != err_status_replay_fail ) {
00385       ast_log(LOG_WARNING, "SRTP unprotect: %s\n", srtp_errstr(res));
00386       errno = EAGAIN;
00387       return -1;
00388    }
00389 
00390    return *len;
00391 }
00392 
00393 static int ast_srtp_protect(struct ast_srtp *srtp, void **buf, int *len, int rtcp)
00394 {
00395    int res;
00396 
00397    if ((*len + SRTP_MAX_TRAILER_LEN) > sizeof(srtp->buf)) {
00398       return -1;
00399    }
00400 
00401    memcpy(srtp->buf, *buf, *len);
00402 
00403    if ((res = rtcp ? srtp_protect_rtcp(srtp->session, srtp->buf, len) : srtp_protect(srtp->session, srtp->buf, len)) != err_status_ok && res != err_status_replay_fail) {
00404       ast_log(LOG_WARNING, "SRTP protect: %s\n", srtp_errstr(res));
00405       return -1;
00406    }
00407 
00408    *buf = srtp->buf;
00409    return *len;
00410 }
00411 
00412 static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy)
00413 {
00414    struct ast_srtp *temp;
00415 
00416    if (!(temp = res_srtp_new())) {
00417       return -1;
00418    }
00419 
00420    if (srtp_create(&temp->session, &policy->sp) != err_status_ok) {
00421       return -1;
00422    }
00423 
00424    ast_module_ref(ast_module_info->self);
00425    temp->rtp = rtp;
00426    *srtp = temp;
00427 
00428    ao2_t_link((*srtp)->policies, policy, "Created initial policy");
00429 
00430    return 0;
00431 }
00432 
00433 static void ast_srtp_destroy(struct ast_srtp *srtp)
00434 {
00435    if (srtp->session) {
00436       srtp_dealloc(srtp->session);
00437    }
00438 
00439    ao2_t_callback(srtp->policies, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "Unallocate policy");
00440    ao2_t_ref(srtp->policies, -1, "Destroying container");
00441 
00442    ast_free(srtp);
00443    ast_module_unref(ast_module_info->self);
00444 }
00445 
00446 static int ast_srtp_add_stream(struct ast_srtp *srtp, struct ast_srtp_policy *policy)
00447 {
00448    struct ast_srtp_policy *match;
00449 
00450    if ((match = find_policy(srtp, &policy->sp, OBJ_POINTER))) {
00451       ast_debug(3, "Policy already exists, not re-adding\n");
00452       ao2_t_ref(match, -1, "Unreffing already existing policy");
00453       return -1;
00454    }
00455 
00456    if (srtp_add_stream(srtp->session, &policy->sp) != err_status_ok) {
00457       return -1;
00458    }
00459 
00460    ao2_t_link(srtp->policies, policy, "Added additional stream");
00461 
00462    return 0;
00463 }
00464 
00465 static int ast_srtp_change_source(struct ast_srtp *srtp, unsigned int from_ssrc, unsigned int to_ssrc)
00466 {
00467    struct ast_srtp_policy *match;
00468    struct srtp_policy_t sp = {
00469       .ssrc.type = ssrc_specific,
00470       .ssrc.value = from_ssrc,
00471    };
00472    err_status_t status;
00473 
00474    /* If we find a mach, return and unlink it from the container so we
00475     * can change the SSRC (which is part of the hash) and then have
00476     * ast_srtp_add_stream link it back in if all is well */
00477    if ((match = find_policy(srtp, &sp, OBJ_POINTER | OBJ_UNLINK))) {
00478       match->sp.ssrc.value = to_ssrc;
00479       if (ast_srtp_add_stream(srtp, match)) {
00480          ast_log(LOG_WARNING, "Couldn't add stream\n");
00481       } else if ((status = srtp_remove_stream(srtp->session, from_ssrc))) {
00482          ast_debug(3, "Couldn't remove stream (%d)\n", status);
00483       }
00484       ao2_t_ref(match, -1, "Unreffing found policy in change_source");
00485    }
00486 
00487    return 0;
00488 }
00489 
00490 static int res_srtp_init(void)
00491 {
00492    if (g_initialized) {
00493       return 0;
00494    }
00495 
00496    if (srtp_init() != err_status_ok) {
00497       return -1;
00498    }
00499 
00500    srtp_install_event_handler(srtp_event_cb);
00501 
00502    return ast_rtp_engine_register_srtp(&srtp_res, &policy_res);
00503 }
00504 
00505 /*
00506  * Exported functions
00507  */
00508 
00509 static int load_module(void)
00510 {
00511    return res_srtp_init();
00512 }
00513 
00514 static int unload_module(void)
00515 {
00516    ast_rtp_engine_unregister_srtp();
00517    return 0;
00518 }
00519 
00520 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Secure RTP (SRTP)",
00521    .load = load_module,
00522    .unload = unload_module,
00523    .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00524 );