xts.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. // Package xts implements the XTS cipher mode as specified in IEEE P1619/D16.
  5. //
  6. // XTS mode is typically used for disk encryption, which presents a number of
  7. // novel problems that make more common modes inapplicable. The disk is
  8. // conceptually an array of sectors and we must be able to encrypt and decrypt
  9. // a sector in isolation. However, an attacker must not be able to transpose
  10. // two sectors of plaintext by transposing their ciphertext.
  11. //
  12. // XTS wraps a block cipher with Rogaway's XEX mode in order to build a
  13. // tweakable block cipher. This allows each sector to have a unique tweak and
  14. // effectively create a unique key for each sector.
  15. //
  16. // XTS does not provide any authentication. An attacker can manipulate the
  17. // ciphertext and randomise a block (16 bytes) of the plaintext. This package
  18. // does not implement ciphertext-stealing so sectors must be a multiple of 16
  19. // bytes.
  20. //
  21. // Note that XTS is usually not appropriate for any use besides disk encryption.
  22. // Most users should use an AEAD mode like GCM (from crypto/cipher.NewGCM) instead.
  23. package xts // import "golang.org/x/crypto/xts"
  24. import (
  25. "crypto/cipher"
  26. "encoding/binary"
  27. "errors"
  28. "sync"
  29. "golang.org/x/crypto/internal/subtle"
  30. )
  31. // Cipher contains an expanded key structure. It is safe for concurrent use if
  32. // the underlying block cipher is safe for concurrent use.
  33. type Cipher struct {
  34. k1, k2 cipher.Block
  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. var tweakPool = sync.Pool{
  40. New: func() interface{} {
  41. return new([blockSize]byte)
  42. },
  43. }
  44. // NewCipher creates a Cipher given a function for creating the underlying
  45. // block cipher (which must have a block size of 16 bytes). The key must be
  46. // twice the length of the underlying cipher's key.
  47. func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) {
  48. c = new(Cipher)
  49. if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil {
  50. return
  51. }
  52. c.k2, err = cipherFunc(key[len(key)/2:])
  53. if c.k1.BlockSize() != blockSize {
  54. err = errors.New("xts: cipher does not have a block size of 16")
  55. }
  56. return
  57. }
  58. // Encrypt encrypts a sector of plaintext and puts the result into ciphertext.
  59. // Plaintext and ciphertext must overlap entirely or not at all.
  60. // Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
  61. func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
  62. if len(ciphertext) < len(plaintext) {
  63. panic("xts: ciphertext is smaller than plaintext")
  64. }
  65. if len(plaintext)%blockSize != 0 {
  66. panic("xts: plaintext is not a multiple of the block size")
  67. }
  68. if subtle.InexactOverlap(ciphertext[:len(plaintext)], plaintext) {
  69. panic("xts: invalid buffer overlap")
  70. }
  71. tweak := tweakPool.Get().(*[blockSize]byte)
  72. for i := range tweak {
  73. tweak[i] = 0
  74. }
  75. binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
  76. c.k2.Encrypt(tweak[:], tweak[:])
  77. for len(plaintext) > 0 {
  78. for j := range tweak {
  79. ciphertext[j] = plaintext[j] ^ tweak[j]
  80. }
  81. c.k1.Encrypt(ciphertext, ciphertext)
  82. for j := range tweak {
  83. ciphertext[j] ^= tweak[j]
  84. }
  85. plaintext = plaintext[blockSize:]
  86. ciphertext = ciphertext[blockSize:]
  87. mul2(tweak)
  88. }
  89. tweakPool.Put(tweak)
  90. }
  91. // Decrypt decrypts a sector of ciphertext and puts the result into plaintext.
  92. // Plaintext and ciphertext must overlap entirely or not at all.
  93. // Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
  94. func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
  95. if len(plaintext) < len(ciphertext) {
  96. panic("xts: plaintext is smaller than ciphertext")
  97. }
  98. if len(ciphertext)%blockSize != 0 {
  99. panic("xts: ciphertext is not a multiple of the block size")
  100. }
  101. if subtle.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) {
  102. panic("xts: invalid buffer overlap")
  103. }
  104. tweak := tweakPool.Get().(*[blockSize]byte)
  105. for i := range tweak {
  106. tweak[i] = 0
  107. }
  108. binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
  109. c.k2.Encrypt(tweak[:], tweak[:])
  110. for len(ciphertext) > 0 {
  111. for j := range tweak {
  112. plaintext[j] = ciphertext[j] ^ tweak[j]
  113. }
  114. c.k1.Decrypt(plaintext, plaintext)
  115. for j := range tweak {
  116. plaintext[j] ^= tweak[j]
  117. }
  118. plaintext = plaintext[blockSize:]
  119. ciphertext = ciphertext[blockSize:]
  120. mul2(tweak)
  121. }
  122. tweakPool.Put(tweak)
  123. }
  124. // mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of
  125. // x¹²⁸ + x⁷ + x² + x + 1.
  126. func mul2(tweak *[blockSize]byte) {
  127. var carryIn byte
  128. for j := range tweak {
  129. carryOut := tweak[j] >> 7
  130. tweak[j] = (tweak[j] << 1) + carryIn
  131. carryIn = carryOut
  132. }
  133. if carryIn != 0 {
  134. // If we have a carry bit then we need to subtract a multiple
  135. // of the irreducible polynomial (x¹²⁸ + x⁷ + x² + x + 1).
  136. // By dropping the carry bit, we're subtracting the x^128 term
  137. // so all that remains is to subtract x⁷ + x² + x + 1.
  138. // Subtraction (and addition) in this representation is just
  139. // XOR.
  140. tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1
  141. }
  142. }