--- srtp/srtp.c (libSRTP 2.1.0, the release) +++ srtp/srtp.c (working copy) @@ -1241,11 +1241,6 @@ 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 */ @@ -2187,7 +2182,7 @@ } else { status = srtp_rdbx_check(&stream->rtp_rdbx, delta); if (status) { - if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx) + if (status != srtp_err_status_replay_fail || !(stream->allow_repeat_tx & 0x01)) return status; /* we've been asked to reuse an index */ } srtp_rdbx_add_index(&stream->rtp_rdbx, delta); @@ -2239,11 +2234,23 @@ 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 @@ -2336,12 +2343,14 @@ 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; @@ -2494,10 +2503,15 @@ /* 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 @@ -2541,7 +2555,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 @@ -2568,7 +2582,11 @@ *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)); @@ -2577,8 +2595,15 @@ 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; + } + } } /*