update packaging
[platform/core/system/edge-orchestration.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. This package
19 // does not implement ciphertext-stealing so sectors must be a multiple of 16
20 // bytes.
21 //
22 // Note that XTS is usually not appropriate for any use besides disk encryption.
23 // Most users should use an AEAD mode like GCM (from crypto/cipher.NewGCM) instead.
24 package xts // import "golang.org/x/crypto/xts"
25
26 import (
27         "crypto/cipher"
28         "encoding/binary"
29         "errors"
30         "sync"
31
32         "golang.org/x/crypto/internal/subtle"
33 )
34
35 // Cipher contains an expanded key structure. It is safe for concurrent use if
36 // the underlying block cipher is safe for concurrent use.
37 type Cipher struct {
38         k1, k2 cipher.Block
39 }
40
41 // blockSize is the block size that the underlying cipher must have. XTS is
42 // only defined for 16-byte ciphers.
43 const blockSize = 16
44
45 var tweakPool = sync.Pool{
46         New: func() interface{} {
47                 return new([blockSize]byte)
48         },
49 }
50
51 // NewCipher creates a Cipher given a function for creating the underlying
52 // block cipher (which must have a block size of 16 bytes). The key must be
53 // twice the length of the underlying cipher's key.
54 func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) {
55         c = new(Cipher)
56         if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil {
57                 return
58         }
59         c.k2, err = cipherFunc(key[len(key)/2:])
60
61         if c.k1.BlockSize() != blockSize {
62                 err = errors.New("xts: cipher does not have a block size of 16")
63         }
64
65         return
66 }
67
68 // Encrypt encrypts a sector of plaintext and puts the result into ciphertext.
69 // Plaintext and ciphertext must overlap entirely or not at all.
70 // Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
71 func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
72         if len(ciphertext) < len(plaintext) {
73                 panic("xts: ciphertext is smaller than plaintext")
74         }
75         if len(plaintext)%blockSize != 0 {
76                 panic("xts: plaintext is not a multiple of the block size")
77         }
78         if subtle.InexactOverlap(ciphertext[:len(plaintext)], plaintext) {
79                 panic("xts: invalid buffer overlap")
80         }
81
82         tweak := tweakPool.Get().(*[blockSize]byte)
83         for i := range tweak {
84                 tweak[i] = 0
85         }
86         binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
87
88         c.k2.Encrypt(tweak[:], tweak[:])
89
90         for len(plaintext) > 0 {
91                 for j := range tweak {
92                         ciphertext[j] = plaintext[j] ^ tweak[j]
93                 }
94                 c.k1.Encrypt(ciphertext, ciphertext)
95                 for j := range tweak {
96                         ciphertext[j] ^= tweak[j]
97                 }
98                 plaintext = plaintext[blockSize:]
99                 ciphertext = ciphertext[blockSize:]
100
101                 mul2(tweak)
102         }
103
104         tweakPool.Put(tweak)
105 }
106
107 // Decrypt decrypts a sector of ciphertext and puts the result into plaintext.
108 // Plaintext and ciphertext must overlap entirely or not at all.
109 // Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
110 func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
111         if len(plaintext) < len(ciphertext) {
112                 panic("xts: plaintext is smaller than ciphertext")
113         }
114         if len(ciphertext)%blockSize != 0 {
115                 panic("xts: ciphertext is not a multiple of the block size")
116         }
117         if subtle.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) {
118                 panic("xts: invalid buffer overlap")
119         }
120
121         tweak := tweakPool.Get().(*[blockSize]byte)
122         for i := range tweak {
123                 tweak[i] = 0
124         }
125         binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
126
127         c.k2.Encrypt(tweak[:], tweak[:])
128
129         for len(ciphertext) > 0 {
130                 for j := range tweak {
131                         plaintext[j] = ciphertext[j] ^ tweak[j]
132                 }
133                 c.k1.Decrypt(plaintext, plaintext)
134                 for j := range tweak {
135                         plaintext[j] ^= tweak[j]
136                 }
137                 plaintext = plaintext[blockSize:]
138                 ciphertext = ciphertext[blockSize:]
139
140                 mul2(tweak)
141         }
142
143         tweakPool.Put(tweak)
144 }
145
146 // mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of
147 // x¹²⁸ + x⁷ + x² + x + 1.
148 func mul2(tweak *[blockSize]byte) {
149         var carryIn byte
150         for j := range tweak {
151                 carryOut := tweak[j] >> 7
152                 tweak[j] = (tweak[j] << 1) + carryIn
153                 carryIn = carryOut
154         }
155         if carryIn != 0 {
156                 // If we have a carry bit then we need to subtract a multiple
157                 // of the irreducible polynomial (x¹²⁸ + x⁷ + x² + x + 1).
158                 // By dropping the carry bit, we're subtracting the x^128 term
159                 // so all that remains is to subtract x⁷ + x² + x + 1.
160                 // Subtraction (and addition) in this representation is just
161                 // XOR.
162                 tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1
163         }
164 }