Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #256 Seq number incorrectly masked for IV. #259

Conversation

mloutris
Copy link

During the IV calculation, the sequence number has it's endianess
reversed before clearing the most significant bit, bit 31.
On little endian platforms, this results in the incorrect clearing
of bit 7. The fix is to clear the most significant bit prior to
swapping the byte order.
Updated the comment to reflect the high order bit is 31, not 30 and to give a rationale for why the high order bit should be cleared.
Please note that this change results in incompatibility with libsrtp
releases without this change.

During the IV calculation, the sequence number has it's endianess
reversed before clearing the most significant bit, bit 31.
On little endian platforms, this results in the incorrect clearing
of bit 7. The fix is to clear the most significant bit prior to
swapping the byte order.
Please note that this change results in incompatibility with libsrtp
releases without this change.
paulej
paulej previously approved these changes Feb 23, 2017
srtp/srtp.c Outdated
/* The SRTCP index (seq_num) spans bits 0 through 30 inclusive.
* Bit 31 must be cleared to zero.
*/
in.v32[2] = htonl((seq_num & 0x7FFFFFFF));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit, but the extra parentheses here doesn't really have any effect.

@mloutris
Copy link
Author

mloutris commented Feb 23, 2017 via email

@JonathanLennox
Copy link

After the fix, isn't this a no-op?

seq_num in srtp_calc_aead_iv_srtcp either comes from srtp_rdb_get_value (where srtp_rdb_increment will refuse to increment past 0x7fffffff) or from ntohl(*trailer) & SRTCP_INDEX_MASK (where SRTCP_INDEX_MASK is defined as 0x7fffffff).

@paulej
Copy link
Contributor

paulej commented Feb 24, 2017

The new code might be a no-op, though the old code is broken. That said, I don't mind this given that it enforces the constraint. Nonetheless, you're right that the sequence number (as the code is current written) will never be greater than 0x7FFFFFFF.

@mloutris
Copy link
Author

mloutris commented Feb 24, 2017 via email

@paulej
Copy link
Contributor

paulej commented Feb 24, 2017

I prefer keeping as you have it, but no strong preference either way. My reasoning is simply that it make it more explicit and you can easily match this with the RFC. But, I have no strong preference. We could just put a comment out to the right indicating that this value is < 0x8000000 and, thus, the MSB will be 0 as required by the RFC.

@JonathanLennox do you have a preference?

@JonathanLennox
Copy link

Do we use asserts anywhere in libsrtp?

This value being greater than 0x7FFFFFFF is a coding error, and if you hit this scenario and just mask it out you'd have a two-time pad problem.

@paulej
Copy link
Contributor

paulej commented Feb 24, 2017

No asserts used (except for some test code: test/rtp_decoder.c).

@pthatcher
Copy link

Should I be concerned that there are no updates to tests?

And if I can weigh in on the "should we have a line of code that does nothing, no line of code"? I'd prefer no line of code, since it's clear from this example that it's easy to get a line of code wrong and cause problems. If the only reason for the line of code would be to handle an invalid seq_num passed in, why not have srtp_calc_aead_iv_srtcp return a srtp_err_status_t and then check that status from two places it is called?

@paulej
Copy link
Contributor

paulej commented Mar 2, 2017

@pthatcher More tests would not hurt. However, it would take at least 128 packets before the problem would be detected. Then the problem would disappear after a while and re-appear. Not sure anyone would think to construct a test that could reproduce exactly this issue.

There are tests for GCM, but they clearly don't test this condition.

The line of code is needed. The only thing not strictly needed (since the value is supposed to be in proper form) is the logical AND. That's all that's in question.

@JonathanLennox
Copy link

I like Peter's suggestion that rather than have the logical AND, we change srtp_calc_aead_iv_srtcp to return srtp_status_t. If its seq_num parameter is greater than 0x7FFFFFFF, return an error (probably srtp_err_status_key_expired).

@paulej
Copy link
Contributor

paulej commented Mar 3, 2017

I added PR #262 in response to the suggestion made by @JonathanLennox and @pthatcher

@pthatcher
Copy link

I like PR #262. Is the idea to merge it, and then merge this one in the form where we remove the logical AND? That sounds the best option to me. (When I said "no line of code", I should have said "no logical AND").

As for unit tests, could we at least add one that tests that if a seq_num >= 0x80000000 is passed in that we return srtp_err_status_bad_param?

@paulej
Copy link
Contributor

paulej commented Mar 3, 2017

@pthatcher Yeah, that was my thinking. We can merge in either order, though.

As for unit tests, we really don't have a framework for that. We could throw something into srtp_validate_gcm() in test/srtp_driver.c, but I'm not very favorable to doing that. I'd prefer if somebody could find time to set up a real unit test framework for all of libsrtp.

@JonathanLennox
Copy link

Unfortunately, the only way to test this is using the external APIs to actually try to encrypt more than 2^31 RTCP packets and then make sure we get the "key exhausted" error. This would be a useful test, but not a quick one. (The RTCP sequence number isn't an external parameter for encryption; for decryption, it's in a field which is only 31 bits wide.)

@thisisG
Copy link
Contributor

thisisG commented Mar 3, 2017

@paulej - I was actually discussing that briefly with @pabuhler today. I would be happy to do this, but unsure of what framework it should be. I'd love something that is single header and provides some type of coverage report, but I am fairly unfamiliar with C unit testing frameworks. Should I perhaps make an issue for discussing this?

@JonathanLennox - Would implementing a unit test framework and exposing functions in srtp_priv.h instead of having static functions in srtp.c be a suitable solution? That way we do not have to test all the way from the public API. Alternatively a set of srtp_interal.[c|h] files could be used in order to expose the functions to a testing framework.

@paulej
Copy link
Contributor

paulej commented Mar 3, 2017

@thisisG I've heard good things said of Google's test framework. I think it's this one: https://github.com/google/googletest. There is also CTest (https://cmake.org/Wiki/CMake/Testing_With_CTest). I don't know which might be better.

I suspect either would allow us to construct unit tests -- even at getting at this function by testing specific values -- without a ton of work. Of course, unit tests are always a bit of work, but I suspect either of these will make things less painful.

@thisisG
Copy link
Contributor

thisisG commented Mar 6, 2017

@paulej - Please see #265 and see if that kind of simple framework would suffice.

@pthatcher - Added a test in the PR mentioned above to check that if seq num exceeds 0x7FFFFFFF we throw an error (depends on #262 ), was this what you had in mind?

@paulej
Copy link
Contributor

paulej commented Mar 6, 2017

ACK. Will look at #265.

@paulej paulej added this to the Version 2.1.0 milestone Mar 10, 2017
Now that there is a check that the 31 bit is 0, the masking becomes a noop and can be removed.
@pabuhler pabuhler dismissed paulej’s stale review March 10, 2017 07:50

Please review after recent changes!

@pabuhler
Copy link
Member

Hi, This change should now reflect what has been discussed, I have removed the previous "approval" and would appreciate if those involved in the discussion to review the change add approval. Once approved it will be merged.

Copy link
Contributor

@thisisG thisisG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@paulej
Copy link
Contributor

paulej commented Mar 10, 2017

Note that the if (seq_num & 0x80000000UL) check is already in master. We'll need to do a manual merge and remove the duplicate.

@paulej paulej merged commit 81046af into cisco:master Mar 10, 2017
imxiangpeng pushed a commit to imxiangpeng/libsrtp that referenced this pull request Mar 24, 2017
During the IV calculation, the sequence number has it's endianess
reversed before clearing the most significant bit, bit 31.

On little endian platforms, this results in the incorrect clearing
of bit 7. The fix is to clear the most significant bit prior to
swapping the byte order.

Please note that this change results in incompatibility with libsrtp
releases without this change.

This is a backport of cisco/libsrtp#259 and
cisco/libsrtp#262

BUG=webrtc:7288
TESTED=Ran all tests using:
gn gen out/libsrtp --args=build_libsrtp_tests=true
ninja -C out/libsrtp srtp_tests
out/libsrtp/srtp_tests/run_all_tests.sh

R=kjellander@chromium.org, pthatcher@chromium.org

Review-Url: https://codereview.chromium.org/2723863003 .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants