--- srtp/srtp.c (libSRTP 1.6.0, the release) +++ srtp/srtp.c (working copy) @@ -744,11 +744,6 @@ 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) { - rdbx_dealloc(&srtp->rtp_rdbx); - return err_status_bad_param; - } srtp->allow_repeat_tx = p->allow_repeat_tx; /* DAM - no RTCP key limit at present */ @@ -1337,7 +1332,7 @@ delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq)); status = rdbx_check(&stream->rtp_rdbx, delta); if (status) { - if (status != err_status_replay_fail || !stream->allow_repeat_tx) + if (status != err_status_replay_fail || !(stream->allow_repeat_tx & 0x01)) return status; /* we've been asked to reuse an index */ } else @@ -1383,11 +1378,23 @@ if (status) return 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 = (((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 @@ -1459,12 +1466,14 @@ unsigned int enc_octet_len = 0;/* number of octets in encrypted portion */ uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ + 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; err_status_t status; srtp_stream_ctx_t *stream; uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; int tag_len, prefix_len; + int retry = 0; debug_print(mod_srtp, "function srtp_unprotect", NULL); @@ -1575,10 +1584,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 = (((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 @@ -1622,7 +1636,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 @@ -1649,7 +1663,11 @@ *pkt_octet_len - tag_len); /* run auth func over ROC, then write tmp tag */ - status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, tmp_tag); + /* Nokia Symbian/S60 calculates auth_tag with little-endian ROC */ + if (retry == 0) + status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, tmp_tag); + else + status = auth_compute(stream->rtp_auth, (uint8_t *)&est_roc_le, 4, tmp_tag); debug_print(mod_srtp, "computed auth tag: %s", octet_string_hex_string(tmp_tag, tag_len)); @@ -1658,8 +1676,15 @@ if (status) return err_status_auth_fail; - if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) - return err_status_auth_fail; + if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) { + if (retry == 0) { + retry = 1; + goto tryagain; + } + else { + return err_status_auth_fail; + } + } } /*