github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/crypto/xts/xts.go (about) 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 // import "golang.org/x/crypto/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 *Cipher, 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 }