[ 
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)

Reply via email to