Git Product home page Git Product logo

Comments (14)

SalusaSecondus avatar SalusaSecondus commented on April 28, 2024 1

PKCS#7 padding is woefully underspecified in that standard. (Let's avoid the whole issue of Java misnaming it as PKCS5Padding). I think that we can safely infer proper padding (pad length must be no greater than the block-size and all bytes must be checked) by looking at a multitude of agreeing sources.

  • RFC 2315/PKCS#7: Section 10.3. Note 2 specifically defines the padding length relative to 'k' (the block-size) and states that the padding will consist of k - (l mod k) octets (which must clearly range from 1 to k).
  • BouncyCastle enforces that PKCS#7 Padding must be minimal
  • The default Java JCE requires that padding be minimal in PKCS5Padding.unpad()
  • OpenSSL also requires that padding be minimal in EVP_DecryptFinal_ex(). b is set to the block-size on line 513.

So, I really do think we have enough of a standard here to enforce. I will agree that I don't immediately see a serious risk of accepting bad padding (which wouldn't exist due to problems elsewhere in the protocol). It at least increases the risk of and simplifies various attacks.

from wycheproof.

bleichen avatar bleichen commented on April 28, 2024

This could possibly be done, though the result might be somewhat unsatisfactory, since even
a good implementation leaves a lot of opportunities for mistakes to the caller.
If the caller uses encrypt-then-mac, and more importantly verify-first-then-decrypt then
it doesn't matter that much whether decryption leaks information through paddings.

Anyway, I'm currently generating test vectors in JSON format for various algorithms, so
it would be possible to do the same for AES/CBC/PKCS5Padding.

Non-constant time unpadding is difficult to detect with the current setup. Even much
larger timing differences (i.e. number of point addition in ECDSA etc) are already difficult
to detect because of noise in typical unit testing.

AES/CBC/PKCS5Padding is one of the first algorithms padded to JCE. Its API is badly broken.
I.e. after a doFinal the Cipher instance is reinitialized with the previous IV. It seems difficult to
actually change this behavior, since implementation might be using it. E.g. I've seen one
implementation that sets the IV to all zero, then encrypts plaintexts by prepending
a random block, claiming that this gives the same result, but faster since an explicit init is slow.
Oracle is fully aware of this design problem, e.g. AES-GCM throws an exception if one tries
to reuse GCM without setting a new IV, but it seems they can't fix the old API.

More ideal for testing here are encryption modes, that by themselves are secure against
chosen message attacks, so that the implementation of the primitive already guarantees
to protect the plaintext and key, and so that testing the primitive can detect flaws, without
having to look at the caller. An example was ECIESWithAES-CBC, which includes an HMAC.
Here, in fact BouncyCastle failed to implement this primitive properly, and checked the
AES padding before checking the HMAC.

from wycheproof.

SalusaSecondus avatar SalusaSecondus commented on April 28, 2024

Fair enough. I was "inspired" to float this idea after seeing two different AES/CBC implementations (one in Java, one in another language) which make many of these mistakes. They are low bars, but that doesn't stop people from tripping over them.

from wycheproof.

bleichen avatar bleichen commented on April 28, 2024

I didn't want to claim that there is no value in testing this,
even though it is a bit unclear what the requirements are.
E.g. I can't find no definition what an acceptable padding is
(I'm using https://tools.ietf.org/html/rfc2315, which is more general than PKCS #5 with respect to block size).
Since padding attacks typically indicate that the whole protocol is badly designed and not just the
PKCS5Padding is weak it is a bit difficult to define acceptable and non-acceptable behavior.
Can an implementation be forgiving when checking the padding? Would it be acceptable
if invalid paddings were accepted because of legacy reasons?

If there is a protocol that promises security against chosen ciphertext attacks
e.g. something like https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05
then it is much easier to nitpick and for example flag exceptions with too much information
as errors.

To give a concrete example:
A random search for aes-cbc hmac gives me this:
https://github.com/glkz/aes-cbc-hmac-sha2/blob/master/lib/Cipher.js
I'm using this library just a illustration. Fortunately, it seems unused.

The last step of the decryption is this:

 decipher.final = function(outputEncoding) {
    var ret = _final.call(decipher, outputEncoding);

    decipher._hmac.update(decipher._aadLength);
    decipher._authTag = decipher._hmac.digest().slice(0, decipher._tagLength);
    decipher._cipherFinalized = true;

    if (!decipher._expectedAuthTag || decipher._authTag.toString('hex') !== decipher._expectedAuthTag.toString('hex')) {
      throw new Error('Authentication failed.');
    }

    return ret;
  };

where the first step _final.call(.) decrypts the last chunk, which of course should remove padding.
Of course this call should be done after checking the HMAC. As written here, the code is incorrect
no matter how the padding check is done and it would be correct no matter how the padding
is checked if the order of HMAC and final were switched (and unrelated bugs were fixed such as
deriving _taglength from the tag passed into the decryption).

from wycheproof.

bleichen avatar bleichen commented on April 28, 2024

Thanks.
So one thing that certainly can be done is provide a number of inputs (key, iv, message) and request that the ciphertext is deterministic. Also requiring that invalid paddings are rejected is reasonable.
Security against padding attacks still seems a bit unclear. E.g. OpenSSL would be faulty if one were strict: EVPerr is a macro that also includes line numbers into the error, hence the lines that you point out
would leak more information than necessary.
At the moment I think padding attacks should be mainly tested on higher levels. Not sure what relevant protocols are: E.g. https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05
is a proposal, but this seems rather unused/dead.

from wycheproof.

jordanmews avatar jordanmews commented on April 28, 2024

I have to question the testcase for pad-length must be less than block-size.
From my understanding, pad-length can be less than or equal to block-size. This is to handle the edge-case where the input-length is a multiple of the blocksize and the possibility that the last character of plaintext could be a 0x01 (or less likely 0x02, 0x02 etc..). The RFC's solution to this is create a whole new block made of only padding characters equal to the blocksize.

I believe that's what's meant by the line in rfc2315:
k k ... k k -- if l mod k = 0

I do have to postface this whole question/comment with the background I'm coming from a place of beginner's mind and could be totally missing something. I do not have the multiple codebase references to back up my question. Just wikipedia (PKCS#7) and a budding interest, but I figured it was a question worth asking.

from wycheproof.

SalusaSecondus avatar SalusaSecondus commented on April 28, 2024

@jordanmews You're correct. Me saying "pad length must be less than block-size" was a mistake and should have been "no greater than the block-size". There is one other place where I incorrectly said that the minimum block-size is 0 rather than 1. Both have been fixed.

As I keep seeing places I wish had these tests, I think that I may draft and submit them.

from wycheproof.

bleichen avatar bleichen commented on April 28, 2024

from wycheproof.

SalusaSecondus avatar SalusaSecondus commented on April 28, 2024

I think that it is useful having tests for the various different paddings. However, I'm not sure which others are currently in (common) cryptographic usage. (I am purposefully excluding hash functions because they never parse/strip the padding, so the test vectors are irrelevant.)

I just recently encountered AES Key Wrap with Padding (RFC 5649) which uses zero padding with a prefixed length. Definitely a construction I haven't seen before and outside of our current tested algorithms. (It also doesn't have a listed JCE Name). So, we should probably wait a while on this one.

from wycheproof.

bleichen avatar bleichen commented on April 28, 2024

from wycheproof.

SalusaSecondus avatar SalusaSecondus commented on April 28, 2024

For RFC 5649, we must test the whole algorithm. I'm just noting that there are potentially some interesting padding cases there we should explicitly cover.

from wycheproof.

thaidn avatar thaidn commented on April 28, 2024

FYI: we just published some test vectors for AES-CBC-PKCS5Padding at https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json.

from wycheproof.

thaidn avatar thaidn commented on April 28, 2024

Re RFC 5649: I believe @bleichen is working on some test vectors for it.

I'm going to close this issue to clean up our queue. Please reopen if you have any further questions or comments.

from wycheproof.

bleichen avatar bleichen commented on April 28, 2024

from wycheproof.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.