[
https://issues.apache.org/jira/browse/HADOOP-11343?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14231868#comment-14231868
]
Mike Yoder commented on HADOOP-11343:
-------------------------------------
What was the proposed solution? I didn't see a difference in the code above
vs. what's in git right now. (I could've missed it...)
The overflow happens at the "l += counter" line, yes? The statement above is
"this overflow gets lost". Well, it doesn't actually get "lost", since this is
integer arithmetic the MAX LONG wraps around to a MIN LONG and keeps going up.
So the effects of the counter are constrained to bytes 8-15 of IV, and bytes
0-7 are fixed at the randomly generated value. We are not concerned with
re-using IVs by wrapping a long - a long is 2^64 bits, and the counter is for
each 16-byte block (or 2^4) so in order to wrap we'd have to have a file that's
2^68 bytes long. Not going to happen.
There actually is no "standard aes-ctr". From
http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf,
{quote}
The Counter (CTR) mode is a confidentiality mode that features the application
of the forward
cipher to a set of input blocks, called counters, to produce a sequence of
output blocks that are
exclusive-ORed with the plaintext to produce the ciphertext, and vice versa.
The sequence of
counters must have the property that each block in the sequence is different
from every other
block. This condition is not restricted to a single message: across all of the
messages that are
encrypted under the given key, all of the counters must be distinct.
{quote}
And from Appendix B of that document:
{quote}
B.2 Choosing Initial Counter Blocks
The initial counter blocks, T1, for each message that is encrypted under the
given key must be
chosen in a manner than ensures the uniqueness of all the counter blocks across
all the messages.
Two examples of approaches to choosing the initial counter blocks are given in
this section.
In the first approach, for a given key, all plaintext messages are encrypted
sequentially. Within
the messages, the same fixed set of m bits of the counter block is incremented
by the standard
incrementing function. The initial counter block for the initial plaintext
message may be any
string of b bits. The initial counter block for any subsequent message can be
obtained by
applying the standard incrementing function to the fixed set of m bits of the
final counter block
of the previous message. In effect, all of the plaintext messages that are ever
encrypted under the
given key are concatenated into a single message; consequently, the total
number of plaintext
blocks must not exceed 2^m . Procedures should be established to ensure the
maintenance of the
state of the final counter block of the latest encrypted message, and to ensure
the proper
sequencing of the messages.
A second approach to satisfying the uniqueness property across messages is to
assign to each
message a unique string of b/2 bits (rounding up, if b is odd), in other words,
a message nonce,
and to incorporate the message nonce into every counter block for the message.
The leading b/2
bits (rounding up, if b is odd) of each counter block would be the message
nonce, and the
standard incrementing function would be applied to the remaining m bits to
provide an index to
the counter blocks for the message. Thus, if N is the message nonce for a given
message, then
the jth counter block is given by Tj = N | \[j], for j = 1…n. The number of
blocks, n, in any
message must satisfy n < 2^m . A procedure should be established to ensure the
uniqueness of the
message nonces.
This recommendation allows other methods and approaches for achieving the
uniqueness
property. Validation that an implementation of the CTR mode conforms to this
recommendation
will typically include an examination of the procedures for assuring the
uniqueness of counter
blocks within messages and across all messages that are encrypted under a given
key.
{quote}
There are two "recommendations", and what's implemented follows the second
recommendation. I believe that most CTR implementations (including Java) do
something like this. (As an aside, I've seen an openssl implementation that
follows the first recommendation.)
Another note is that if this function is altered in any way, it will break the
decryption of data that has already been encrypted. I don't know if that's
much at all at this point, but one would still have to tread with care.
I recommend that we leave this function alone... unless I misunderstood
something about the problem.
> Overflow is not properly handled in caclulating final iv for AES CTR
> --------------------------------------------------------------------
>
> Key: HADOOP-11343
> URL: https://issues.apache.org/jira/browse/HADOOP-11343
> Project: Hadoop Common
> Issue Type: Bug
> Components: security
> Affects Versions: trunk-win
> Reporter: Jerry Chen
>
> In the AesCtrCryptoCodec calculateIV, as the init IV is a random generated 16
> bytes,
> final byte[] iv = new byte[cc.getCipherSuite().getAlgorithmBlockSize()];
> cc.generateSecureRandom(iv);
> Then the following calculation of iv and counter on 8 bytes (64bit) space
> would easily cause overflow and this overflow gets lost. The result would be
> the 128 bit data block was encrypted with a wrong counter and cannot be
> decrypted by standard aes-ctr.
> /**
> * The IV is produced by adding the initial IV to the counter. IV length
> * should be the same as {@link #AES_BLOCK_SIZE}
> */
> @Override
> public void calculateIV(byte[] initIV, long counter, byte[] IV) {
> Preconditions.checkArgument(initIV.length == AES_BLOCK_SIZE);
> Preconditions.checkArgument(IV.length == AES_BLOCK_SIZE);
>
> System.arraycopy(initIV, 0, IV, 0, CTR_OFFSET);
> long l = 0;
> for (int i = 0; i < 8; i++) {
> l = ((l << 8) | (initIV[CTR_OFFSET + i] & 0xff));
> }
> l += counter;
> IV[CTR_OFFSET + 0] = (byte) (l >>> 56);
> IV[CTR_OFFSET + 1] = (byte) (l >>> 48);
> IV[CTR_OFFSET + 2] = (byte) (l >>> 40);
> IV[CTR_OFFSET + 3] = (byte) (l >>> 32);
> IV[CTR_OFFSET + 4] = (byte) (l >>> 24);
> IV[CTR_OFFSET + 5] = (byte) (l >>> 16);
> IV[CTR_OFFSET + 6] = (byte) (l >>> 8);
> IV[CTR_OFFSET + 7] = (byte) (l);
> }
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)