OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / xts / xts.go
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         "encoding/binary"
27         "errors"
28 )
29
30 // Cipher contains an expanded key structure. It doesn't contain mutable state
31 // and therefore can be used concurrently.
32 type Cipher struct {
33         k1, k2 cipher.Block
34 }
35
36 // blockSize is the block size that the underlying cipher must have. XTS is
37 // only defined for 16-byte ciphers.
38 const blockSize = 16
39
40 // NewCipher creates a Cipher given a function for creating the underlying
41 // block cipher (which must have a block size of 16 bytes). The key must be
42 // twice the length of the underlying cipher's key.
43 func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) {
44         c = new(Cipher)
45         if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil {
46                 return
47         }
48         c.k2, err = cipherFunc(key[len(key)/2:])
49
50         if c.k1.BlockSize() != blockSize {
51                 err = errors.New("xts: cipher does not have a block size of 16")
52         }
53
54         return
55 }
56
57 // Encrypt encrypts a sector of plaintext and puts the result into ciphertext.
58 // Plaintext and ciphertext may be the same slice but should not overlap.
59 // Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
60 func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
61         if len(ciphertext) < len(plaintext) {
62                 panic("xts: ciphertext is smaller than plaintext")
63         }
64         if len(plaintext)%blockSize != 0 {
65                 panic("xts: plaintext is not a multiple of the block size")
66         }
67
68         var tweak [blockSize]byte
69         binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
70
71         c.k2.Encrypt(tweak[:], tweak[:])
72
73         for len(plaintext) > 0 {
74                 for j := range tweak {
75                         ciphertext[j] = plaintext[j] ^ tweak[j]
76                 }
77                 c.k1.Encrypt(ciphertext, ciphertext)
78                 for j := range tweak {
79                         ciphertext[j] ^= tweak[j]
80                 }
81                 plaintext = plaintext[blockSize:]
82                 ciphertext = ciphertext[blockSize:]
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         binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
101
102         c.k2.Encrypt(tweak[:], tweak[:])
103
104         for len(ciphertext) > 0 {
105                 for j := range tweak {
106                         plaintext[j] = ciphertext[j] ^ tweak[j]
107                 }
108                 c.k1.Decrypt(plaintext, plaintext)
109                 for j := range tweak {
110                         plaintext[j] ^= tweak[j]
111                 }
112                 plaintext = plaintext[blockSize:]
113                 ciphertext = ciphertext[blockSize:]
114
115                 mul2(&tweak)
116         }
117 }
118
119 // mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of
120 // x¹²⁸ + x⁷ + x² + x + 1.
121 func mul2(tweak *[blockSize]byte) {
122         var carryIn byte
123         for j := range tweak {
124                 carryOut := tweak[j] >> 7
125                 tweak[j] = (tweak[j] << 1) + carryIn
126                 carryIn = carryOut
127         }
128         if carryIn != 0 {
129                 // If we have a carry bit then we need to subtract a multiple
130                 // of the irreducible polynomial (x¹²⁸ + x⁷ + x² + x + 1).
131                 // By dropping the carry bit, we're subtracting the x^128 term
132                 // so all that remains is to subtract x⁷ + x² + x + 1.
133                 // Subtraction (and addition) in this representation is just
134                 // XOR.
135                 tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1
136         }
137 }