I finally found a few quite hours to think about this. The executive summary of this (rather long) note is:
(a) The ciphertext-stealing extension can be shown to be "as strong as LRW" (in some reasonable model). The proof essentially shows that anything that an attacker can do when interacting with the extended mode can also be done when interacting with the basic LRW. (b) The "LBA to I mapping" is not quite the right question to discuss, it should be "tweak to T mapping". (Recall that T is what you get when multiplying I by Key_2.) I discuss below some of the proposals that where raised and also suggest another alternative. To make this note a bit less cluttered, I attach the discussion of these two topics in two separate files (both ascii text). Below are some minor comments about some issues that came up in the discussion. [EMAIL PROTECTED] wrote: > If the encryption is done in each individual disk drive, you just have > to provide a different key for each. They can be K, K+1, K+2,... You should not be using K+1, K+2, etc, lest you run into related-key attacks. > I could not explain my concerns clearly enough about small block > encryption (~LRW) outside of the disk drive, so here I try it again. > (Because of protests, we did not discuss this in the last P1619 > meeting.) [...] > In this view, reasonable security is only achieved in practice, if the > encryption is done internally in the disk drive. [...] This discussion is valuable and should be written as a white-paper, but in my view it has no place in the standard itself. (Is there such a thing as "supporting documents" for a standard?) > For the cases, where traffic analysis is a feasible attack, P1619 should > revive one of the long block encryption modes. The reason that I withdrew EME was that no one had shown any interest in using it. We discussed in the past the possibility of writing another standard (maybe p1619.2) that would describe other modes that are "cryptographically strong" but have no aspects of interoperability. We can put the wide-block modes in that standard. Michael Torla wrote: > Recall that I is the index within the scope of the second key K2. > In a system with multiple K2's {K2_1 .. K2_n} > [...] > Unless scoping restrictions are documented in the specification, > you have to assume the worst case deployment for K1 and K2. For > worst case, I would assume that K1 applies to every disk drive > deployed at the US Government, and that a different K2 is applied > to every sector in every disk drive. This usage should be disallowed by the standard. (I think that it is not allowed by the current draft, and if I'm wrong then we need to change the language so as to exclude it.) LRW is a single transform, and it takes a 48-byte secret key. The users of LRW should not care how this key is used inside the transform. If they use several different keys, then all the 48 bytes have to be chosen "at random and independently" for each of these different keys. -- Shai
Roughly, the security analysis of LRW is done in a model with an attacker that has arbitrary access to the encryption and decryption routines for every block on the disk. In this model, the attacker is successful if it can distinguish between the following two vases: (a) The system is indeed using LRW, or (b) Every block of the disk is encrypted using a truly random permutation, and moreover all these permutations are independent of each other. The LRW theorem tells you that any attacker that can distinguish these two cases can also distinguish AES from a random permutation (with about the same advantage). Since it is commonly accepted that no feasible attacker can distinguish AES from a truly random permutation with any noticeable advantage, this implies that no feasible attacker can distinguish between cases (a) and (b) above. (BTW, that proof works just as well when you have "tweak" value of zero.) Why is any of it relevant to the security of LRW in our application? The rationale is as follows: First, no realistic attacker would have more information than the attacker in the mathematical model. So also no realistic attacker can distinguish between cases (a) and (b). Which means that whatever attack we are facing would be just as successful if we were using case (b) to encrypt our disk rather than using LRW. This is where the "security proof" of LRW ends. The rest is specific to the implementations. That is, for a specific implementation you can ask whether case (b) above provides sufficient security, and if it does then that implementation can safely use LRW. As Laszlo explained, there are cases where even (b) does not buy you enough security (e.g., from traffic analysis). Looking at the extended LRW mode, it is easy to see that anything that an attacker can do against this extended mode can also be done by the attacker in the original mathematical mode. If the new attacker asks to encrypt P_I P_{I+1} (with P_{I+1} a partial block), the attacker from the model would first ask to encrypt P_I (and get C_I and C') and then ask to encrypt the block (P_{I+1} C') thus getting C_{I+1}. So also for the extended mode one cannot distinguish using the mode from using truly random and independent permutations, and the same rationale as above tells you that this implies security for the extended LRW in our application.
The LRW paper [1] defines the mode LRW(K1,K2; tweak; plaintext) = Cipher(K1; plaintext xor T) xor T where T is computed from K2 and the tweak. For this to be secure, you need that for any two different fixed values tweak and tweak', if you choose K2 at random and compute T and T' then (T xor T') is a random n-bit string. (They really need a slightly weaker property, but no matter.) In the current draft, the suggestion is to view the tweak as a sequence number of the current block within the scope of the key (call it I), and then compute T = I * K2 where the product is defined as multiplication in the field GF(2^128). This clearly has the needed property (even if you allow the case I=0). In the discussion so far it was argued that computing T in this way from the values that are available to the encryption device may not be optimal. In particular, it was suggested that the tweak value should consist of two or three indexes: the index of the current LBA (or sector), the index of the current block in the sector, and maybe also the index of the current disk. I suggest that we introduce the notion of "compartments" within the key-scope, and use exactly two two indexes, namely the compartment index and the index of the block within the compartment. The expectation is that access to different compartments be more or less random-access, but blocks within a compartment will be accessed sequentially. (So the compartment could be an LBA or LBA+disk index.) I am not sure to what extent do we need to standardize the mapping between these indexes and the information that is available to the encryption device in the various settings that were discussed so far (or in other settings that can dream of). My feeling is that we should specify the mapping only for the case where there is one key per disk (or virtual disk, or LUN, or volume, or whatever unit the encryption device thinks it should manage). Assuming that we indeed have these two indexes (with the usage assumption as above), the suggestions that were discussed on the mailing list are essentially to first compute I = compartment-index * Some-number + block-index and then to compute T = K2 * I as before, where Some-number is either a big enough constant or something which is derived from the other information that is available to the encrypting device. Between these options I prefer to have Some-number as a constant that is specified in the standard, because it make the standard less sensitive to usage details (i.e., we don't need to have in the standard a long list of "if you are in this environment then compute X, if you are in that environment then compute Y, else compute Z"). Also, using a large fixed number for Some-number seems easy to optimize: one stores both K2 and K2' = K2 * Some-number, and then computes T = compartment-index * K2' xor block-index * K2 (this gives the right answer if Some-number is a power of two and block-index does not exceed Some-number). A different proposal is to use two 128-bit values for K2, call them K2a and K2b, and compute T = K2a * compartment-index xor K2b * 2^{block-index} (All the operations here are in the field GF(2^128).) The reason that I propose to use K2b * 2^{block-index} instead of K2b * block-index is that it makes it easier to compute the next T from the current one (here we use the assumption that the block-index is incremented sequentially). You no longer need to worry about carry bits and the like. This would make the LRW key 64 bytes rather than 48 bytes. If people think that this is big deal (and I don't see why it would be) then perhaps there are simple ways of deriving both K2a and K2b from the same 16-byte key K2 (but that requires additional study).