--- srtp/srtp.c (libSRTP 2.2.0, the release) +++ srtp/srtp.c (working copy) @@ -1259,11 +1259,6 @@ srtp_stream_init srtp_rdb_init(&srtp->rtcp_rdb); /* initialize allow_repeat_tx */ - /* guard against uninitialized memory: allow only 0 or 1 here */ - if (p->allow_repeat_tx != 0 && p->allow_repeat_tx != 1) { - srtp_rdbx_dealloc(&srtp->rtp_rdbx); - return srtp_err_status_bad_param; - } srtp->allow_repeat_tx = p->allow_repeat_tx; /* DAM - no RTCP key limit at present */ @@ -2221,7 +2216,7 @@ srtp_protect_mki status = srtp_rdbx_check(&stream->rtp_rdbx, delta); if (status) { if (status != srtp_err_status_replay_fail || - !stream->allow_repeat_tx) + !(stream->allow_repeat_tx & 0x01)) return status; /* we've been asked to reuse an index */ } srtp_rdbx_add_index(&stream->rtp_rdbx, delta); @@ -2277,10 +2272,23 @@ srtp_protect_mki if (status) return srtp_err_status_cipher_fail; -/* shift est, put into network byte order */ +/* shift est, put into network byte order (part 1) */ +#ifdef NO_64BIT_MATH + est = make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16); +#endif + + /* Nokia Symbian/S60 requires little-endian ROC */ + if (stream->allow_repeat_tx & 0x02) { #ifdef NO_64BIT_MATH - est = be64_to_cpu( - make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); + est = make64(bswap_32(high32(est)), low32(est)); +#else + est = (((srtp_xtd_seq_num_t) bswap_32(est >> 16)) << 16) | (est & 0xffff); +#endif + } + + /* shift est, put into network byte order (part 2) */ +#ifdef NO_64BIT_MATH + est = be64_to_cpu(est); #else est = be64_to_cpu(est << 16); #endif @@ -2377,12 +2385,14 @@ srtp_unprotect_mki unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ + srtp_xtd_seq_num_t est_roc_le; /* see est; here, ROC is in little-endian */ int delta; /* delta of local pkt idx and that in hdr */ v128_t iv; srtp_err_status_t status; srtp_stream_ctx_t *stream; uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; uint32_t tag_len, prefix_len; + int retry = 0; srtp_hdr_xtnd_t *xtn_hdr = NULL; unsigned int mki_size = 0; srtp_session_keys_t *session_keys = NULL; @@ -2531,9 +2541,14 @@ srtp_unprotect_mki /* shift est, put into network byte order */ #ifdef NO_64BIT_MATH + est_roc_le = make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16); + est_roc_le = make64(bswap_32(high32(est_roc_le)), low32(est_roc_le)); + est_roc_le = be64_to_cpu(est_roc_le); est = be64_to_cpu( make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); #else + est_roc_le = (((srtp_xtd_seq_num_t) bswap_32(est >> 16)) << 16) | (est & 0xffff); + est_roc_le = be64_to_cpu(est_roc_le << 16); est = be64_to_cpu(est << 16); #endif @@ -2578,6 +2593,7 @@ * function and compare the result with the value of the auth_tag */ if (auth_start) { +tryagain: /* * if we're using a universal hash, then we need to compute the * keystream prefix for encrypting the universal hash output @@ -2605,8 +2621,12 @@ *pkt_octet_len - tag_len - mki_size); /* run auth func over ROC, then write tmp tag */ - status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, - tmp_tag); + /* Nokia Symbian/S60 calculates auth_tag with little-endian ROC */ + if (retry == 0) { + status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, tmp_tag); + } else { + status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est_roc_le, 4, tmp_tag); + } debug_print(mod_srtp, "computed auth tag: %s", srtp_octet_string_hex_string(tmp_tag, tag_len)); @@ -2615,8 +2635,14 @@ if (status) return srtp_err_status_auth_fail; - if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) - return srtp_err_status_auth_fail; + if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) { + if (retry == 0) { + retry = 1; + goto tryagain; + } else { + return srtp_err_status_auth_fail; + } + } } /*