OLD | NEW |
(Empty) | |
| 1 // Copyright 2012 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 // Package xts implements the XTS cipher mode as specified in IEEE P1619/D16. |
| 6 // |
| 7 // XTS mode is typically used for disk encryption, which presents a number of |
| 8 // novel problems that make more common modes inapplicable. The disk is |
| 9 // conceptually an array of sectors and we must be able to encrypt and decrypt |
| 10 // a sector in isolation. However, an attacker must not be able to transpose |
| 11 // two sectors of plaintext by transposing their ciphertext. |
| 12 // |
| 13 // XTS wraps a block cipher with Rogaway's XEX mode in order to build a |
| 14 // tweakable block cipher. This allows each sector to have a unique tweak and |
| 15 // effectively create a unique key for each sector. |
| 16 // |
| 17 // XTS does not provide any authentication. An attacker can manipulate the |
| 18 // ciphertext and randomise a block (16 bytes) of the plaintext. |
| 19 // |
| 20 // (Note: this package does not implement ciphertext-stealing so sectors must |
| 21 // be a multiple of 16 bytes.) |
| 22 package xts |
| 23 |
| 24 import ( |
| 25 "crypto/cipher" |
| 26 "errors" |
| 27 ) |
| 28 |
| 29 // Cipher contains an expanded key structure. It doesn't contain mutable state |
| 30 // and therefore can be used concurrently. |
| 31 type Cipher struct { |
| 32 k1, k2 cipher.Block |
| 33 } |
| 34 |
| 35 // blockSize is the block size that the underlying cipher must have. XTS is |
| 36 // only defined for 16-byte ciphers. |
| 37 const blockSize = 16 |
| 38 |
| 39 // NewCipher creates a Cipher given a function for creating the underlying |
| 40 // block cipher (which must have a block size of 16 bytes). The key must be |
| 41 // twice the length of the underlying cipher's key. |
| 42 func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Ci
pher, err error) { |
| 43 c = new(Cipher) |
| 44 if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil { |
| 45 return |
| 46 } |
| 47 c.k2, err = cipherFunc(key[len(key)/2:]) |
| 48 |
| 49 if c.k1.BlockSize() != blockSize { |
| 50 err = errors.New("xts: cipher does not have a block size of 16") |
| 51 } |
| 52 |
| 53 return |
| 54 } |
| 55 |
| 56 // Encrypt encrypts a sector of plaintext and puts the result into ciphertext. |
| 57 // Plaintext and ciphertext may be the same slice but should not overlap. |
| 58 // Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. |
| 59 func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { |
| 60 if len(ciphertext) < len(plaintext) { |
| 61 panic("xts: ciphertext is smaller than plaintext") |
| 62 } |
| 63 if len(plaintext)%blockSize != 0 { |
| 64 panic("xts: plaintext is not a multiple of the block size") |
| 65 } |
| 66 |
| 67 var tweak [blockSize]byte |
| 68 for i := 0; i < 8; i++ { |
| 69 tweak[i] = byte(sectorNum) |
| 70 sectorNum >>= 8 |
| 71 } |
| 72 |
| 73 c.k2.Encrypt(tweak[:], tweak[:]) |
| 74 |
| 75 for i := 0; i < len(plaintext); i += blockSize { |
| 76 for j := 0; j < blockSize; j++ { |
| 77 ciphertext[i+j] = plaintext[i+j] ^ tweak[j] |
| 78 } |
| 79 c.k1.Encrypt(ciphertext[i:], ciphertext[i:]) |
| 80 for j := 0; j < blockSize; j++ { |
| 81 ciphertext[i+j] ^= tweak[j] |
| 82 } |
| 83 |
| 84 mul2(&tweak) |
| 85 } |
| 86 } |
| 87 |
| 88 // Decrypt decrypts a sector of ciphertext and puts the result into plaintext. |
| 89 // Plaintext and ciphertext may be the same slice but should not overlap. |
| 90 // Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. |
| 91 func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { |
| 92 if len(plaintext) < len(ciphertext) { |
| 93 panic("xts: plaintext is smaller than ciphertext") |
| 94 } |
| 95 if len(ciphertext)%blockSize != 0 { |
| 96 panic("xts: ciphertext is not a multiple of the block size") |
| 97 } |
| 98 |
| 99 var tweak [blockSize]byte |
| 100 for i := 0; i < 8; i++ { |
| 101 tweak[i] = byte(sectorNum) |
| 102 sectorNum >>= 8 |
| 103 } |
| 104 |
| 105 c.k2.Encrypt(tweak[:], tweak[:]) |
| 106 |
| 107 for i := 0; i < len(plaintext); i += blockSize { |
| 108 for j := 0; j < blockSize; j++ { |
| 109 plaintext[i+j] = ciphertext[i+j] ^ tweak[j] |
| 110 } |
| 111 c.k1.Decrypt(plaintext[i:], plaintext[i:]) |
| 112 for j := 0; j < blockSize; j++ { |
| 113 plaintext[i+j] ^= tweak[j] |
| 114 } |
| 115 |
| 116 mul2(&tweak) |
| 117 } |
| 118 } |
| 119 |
| 120 // mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of |
| 121 // x¹²⁸ + x⁷ + x² + x + 1. |
| 122 func mul2(tweak *[blockSize]byte) { |
| 123 var carryIn byte |
| 124 for j := range tweak { |
| 125 carryOut := tweak[j] >> 7 |
| 126 tweak[j] = (tweak[j] << 1) + carryIn |
| 127 carryIn = carryOut |
| 128 } |
| 129 if carryIn != 0 { |
| 130 // If we have a carry bit then we need to subtract a multiple |
| 131 // of the irreducible polynomial (x¹²⁸ + x⁷ + x² + x + 1). |
| 132 // By dropping the carry bit, we're subtracting the x^128 term |
| 133 // so all that remains is to subtract x⁷ + x² + x + 1. |
| 134 // Subtraction (and addition) in this representation is just |
| 135 // XOR. |
| 136 tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1 |
| 137 } |
| 138 } |
OLD | NEW |