Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1537)

Side by Side Diff: xts/xts.go

Issue 6392050: code review 6392050: xts: add package. (Closed)
Patch Set: diff -r 942ebd6029e7 https://code.google.com/p/go.crypto Created 11 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | xts/xts_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
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 *Ci pher, 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 }
OLDNEW
« no previous file with comments | « no previous file | xts/xts_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b