~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/golang.org/x/crypto/xts/xts.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}