Home | History | Annotate | Download | only in cipher
      1 // Copyright 2013 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 cipher
      6 
      7 import (
      8 	"crypto/subtle"
      9 	"errors"
     10 )
     11 
     12 // AEAD is a cipher mode providing authenticated encryption with associated
     13 // data.
     14 type AEAD interface {
     15 	// NonceSize returns the size of the nonce that must be passed to Seal
     16 	// and Open.
     17 	NonceSize() int
     18 
     19 	// Overhead returns the maximum difference between the lengths of a
     20 	// plaintext and ciphertext.
     21 	Overhead() int
     22 
     23 	// Seal encrypts and authenticates plaintext, authenticates the
     24 	// additional data and appends the result to dst, returning the updated
     25 	// slice. The nonce must be NonceSize() bytes long and unique for all
     26 	// time, for a given key.
     27 	//
     28 	// The plaintext and dst may alias exactly or not at all.
     29 	Seal(dst, nonce, plaintext, data []byte) []byte
     30 
     31 	// Open decrypts and authenticates ciphertext, authenticates the
     32 	// additional data and, if successful, appends the resulting plaintext
     33 	// to dst, returning the updated slice. The nonce must be NonceSize()
     34 	// bytes long and both it and the additional data must match the
     35 	// value passed to Seal.
     36 	//
     37 	// The ciphertext and dst may alias exactly or not at all.
     38 	Open(dst, nonce, ciphertext, data []byte) ([]byte, error)
     39 }
     40 
     41 // gcmFieldElement represents a value in GF(2). In order to reflect the GCM
     42 // standard and make getUint64 suitable for marshaling these values, the bits
     43 // are stored backwards. For example:
     44 //   the coefficient of x can be obtained by v.low >> 63.
     45 //   the coefficient of x can be obtained by v.low & 1.
     46 //   the coefficient of x can be obtained by v.high >> 63.
     47 //   the coefficient of x can be obtained by v.high & 1.
     48 type gcmFieldElement struct {
     49 	low, high uint64
     50 }
     51 
     52 // gcm represents a Galois Counter Mode with a specific key. See
     53 // http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
     54 type gcm struct {
     55 	cipher    Block
     56 	nonceSize int
     57 	// productTable contains the first sixteen powers of the key, H.
     58 	// However, they are in bit reversed order. See NewGCMWithNonceSize.
     59 	productTable [16]gcmFieldElement
     60 }
     61 
     62 // NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode
     63 // with the standard nonce length.
     64 func NewGCM(cipher Block) (AEAD, error) {
     65 	return NewGCMWithNonceSize(cipher, gcmStandardNonceSize)
     66 }
     67 
     68 // NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois
     69 // Counter Mode, which accepts nonces of the given length.
     70 //
     71 // Only use this function if you require compatibility with an existing
     72 // cryptosystem that uses non-standard nonce lengths. All other users should use
     73 // NewGCM, which is faster and more resistant to misuse.
     74 func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) {
     75 	if cipher.BlockSize() != gcmBlockSize {
     76 		return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
     77 	}
     78 
     79 	var key [gcmBlockSize]byte
     80 	cipher.Encrypt(key[:], key[:])
     81 
     82 	g := &gcm{cipher: cipher, nonceSize: size}
     83 
     84 	// We precompute 16 multiples of |key|. However, when we do lookups
     85 	// into this table we'll be using bits from a field element and
     86 	// therefore the bits will be in the reverse order. So normally one
     87 	// would expect, say, 4*key to be in index 4 of the table but due to
     88 	// this bit ordering it will actually be in index 0010 (base 2) = 2.
     89 	x := gcmFieldElement{
     90 		getUint64(key[:8]),
     91 		getUint64(key[8:]),
     92 	}
     93 	g.productTable[reverseBits(1)] = x
     94 
     95 	for i := 2; i < 16; i += 2 {
     96 		g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)])
     97 		g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x)
     98 	}
     99 
    100 	return g, nil
    101 }
    102 
    103 const (
    104 	gcmBlockSize         = 16
    105 	gcmTagSize           = 16
    106 	gcmStandardNonceSize = 12
    107 )
    108 
    109 func (g *gcm) NonceSize() int {
    110 	return g.nonceSize
    111 }
    112 
    113 func (*gcm) Overhead() int {
    114 	return gcmTagSize
    115 }
    116 
    117 func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
    118 	if len(nonce) != g.nonceSize {
    119 		panic("cipher: incorrect nonce length given to GCM")
    120 	}
    121 	ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize)
    122 
    123 	var counter, tagMask [gcmBlockSize]byte
    124 	g.deriveCounter(&counter, nonce)
    125 
    126 	g.cipher.Encrypt(tagMask[:], counter[:])
    127 	gcmInc32(&counter)
    128 
    129 	g.counterCrypt(out, plaintext, &counter)
    130 	g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask)
    131 
    132 	return ret
    133 }
    134 
    135 var errOpen = errors.New("cipher: message authentication failed")
    136 
    137 func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
    138 	if len(nonce) != g.nonceSize {
    139 		panic("cipher: incorrect nonce length given to GCM")
    140 	}
    141 
    142 	if len(ciphertext) < gcmTagSize {
    143 		return nil, errOpen
    144 	}
    145 	tag := ciphertext[len(ciphertext)-gcmTagSize:]
    146 	ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
    147 
    148 	var counter, tagMask [gcmBlockSize]byte
    149 	g.deriveCounter(&counter, nonce)
    150 
    151 	g.cipher.Encrypt(tagMask[:], counter[:])
    152 	gcmInc32(&counter)
    153 
    154 	var expectedTag [gcmTagSize]byte
    155 	g.auth(expectedTag[:], ciphertext, data, &tagMask)
    156 
    157 	if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 {
    158 		return nil, errOpen
    159 	}
    160 
    161 	ret, out := sliceForAppend(dst, len(ciphertext))
    162 	g.counterCrypt(out, ciphertext, &counter)
    163 
    164 	return ret, nil
    165 }
    166 
    167 // reverseBits reverses the order of the bits of 4-bit number in i.
    168 func reverseBits(i int) int {
    169 	i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
    170 	i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
    171 	return i
    172 }
    173 
    174 // gcmAdd adds two elements of GF(2) and returns the sum.
    175 func gcmAdd(x, y *gcmFieldElement) gcmFieldElement {
    176 	// Addition in a characteristic 2 field is just XOR.
    177 	return gcmFieldElement{x.low ^ y.low, x.high ^ y.high}
    178 }
    179 
    180 // gcmDouble returns the result of doubling an element of GF(2).
    181 func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) {
    182 	msbSet := x.high&1 == 1
    183 
    184 	// Because of the bit-ordering, doubling is actually a right shift.
    185 	double.high = x.high >> 1
    186 	double.high |= x.low << 63
    187 	double.low = x.low >> 1
    188 
    189 	// If the most-significant bit was set before shifting then it,
    190 	// conceptually, becomes a term of x^128. This is greater than the
    191 	// irreducible polynomial so the result has to be reduced. The
    192 	// irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to
    193 	// eliminate the term at x^128 which also means subtracting the other
    194 	// four terms. In characteristic 2 fields, subtraction == addition ==
    195 	// XOR.
    196 	if msbSet {
    197 		double.low ^= 0xe100000000000000
    198 	}
    199 
    200 	return
    201 }
    202 
    203 var gcmReductionTable = []uint16{
    204 	0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
    205 	0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
    206 }
    207 
    208 // mul sets y to y*H, where H is the GCM key, fixed during NewGCMWithNonceSize.
    209 func (g *gcm) mul(y *gcmFieldElement) {
    210 	var z gcmFieldElement
    211 
    212 	for i := 0; i < 2; i++ {
    213 		word := y.high
    214 		if i == 1 {
    215 			word = y.low
    216 		}
    217 
    218 		// Multiplication works by multiplying z by 16 and adding in
    219 		// one of the precomputed multiples of H.
    220 		for j := 0; j < 64; j += 4 {
    221 			msw := z.high & 0xf
    222 			z.high >>= 4
    223 			z.high |= z.low << 60
    224 			z.low >>= 4
    225 			z.low ^= uint64(gcmReductionTable[msw]) << 48
    226 
    227 			// the values in |table| are ordered for
    228 			// little-endian bit positions. See the comment
    229 			// in NewGCMWithNonceSize.
    230 			t := &g.productTable[word&0xf]
    231 
    232 			z.low ^= t.low
    233 			z.high ^= t.high
    234 			word >>= 4
    235 		}
    236 	}
    237 
    238 	*y = z
    239 }
    240 
    241 // updateBlocks extends y with more polynomial terms from blocks, based on
    242 // Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks.
    243 func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) {
    244 	for len(blocks) > 0 {
    245 		y.low ^= getUint64(blocks)
    246 		y.high ^= getUint64(blocks[8:])
    247 		g.mul(y)
    248 		blocks = blocks[gcmBlockSize:]
    249 	}
    250 }
    251 
    252 // update extends y with more polynomial terms from data. If data is not a
    253 // multiple of gcmBlockSize bytes long then the remainder is zero padded.
    254 func (g *gcm) update(y *gcmFieldElement, data []byte) {
    255 	fullBlocks := (len(data) >> 4) << 4
    256 	g.updateBlocks(y, data[:fullBlocks])
    257 
    258 	if len(data) != fullBlocks {
    259 		var partialBlock [gcmBlockSize]byte
    260 		copy(partialBlock[:], data[fullBlocks:])
    261 		g.updateBlocks(y, partialBlock[:])
    262 	}
    263 }
    264 
    265 // gcmInc32 treats the final four bytes of counterBlock as a big-endian value
    266 // and increments it.
    267 func gcmInc32(counterBlock *[16]byte) {
    268 	for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- {
    269 		counterBlock[i]++
    270 		if counterBlock[i] != 0 {
    271 			break
    272 		}
    273 	}
    274 }
    275 
    276 // sliceForAppend takes a slice and a requested number of bytes. It returns a
    277 // slice with the contents of the given slice followed by that many bytes and a
    278 // second slice that aliases into it and contains only the extra bytes. If the
    279 // original slice has sufficient capacity then no allocation is performed.
    280 func sliceForAppend(in []byte, n int) (head, tail []byte) {
    281 	if total := len(in) + n; cap(in) >= total {
    282 		head = in[:total]
    283 	} else {
    284 		head = make([]byte, total)
    285 		copy(head, in)
    286 	}
    287 	tail = head[len(in):]
    288 	return
    289 }
    290 
    291 // counterCrypt crypts in to out using g.cipher in counter mode.
    292 func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
    293 	var mask [gcmBlockSize]byte
    294 
    295 	for len(in) >= gcmBlockSize {
    296 		g.cipher.Encrypt(mask[:], counter[:])
    297 		gcmInc32(counter)
    298 
    299 		xorWords(out, in, mask[:])
    300 		out = out[gcmBlockSize:]
    301 		in = in[gcmBlockSize:]
    302 	}
    303 
    304 	if len(in) > 0 {
    305 		g.cipher.Encrypt(mask[:], counter[:])
    306 		gcmInc32(counter)
    307 		xorBytes(out, in, mask[:])
    308 	}
    309 }
    310 
    311 // deriveCounter computes the initial GCM counter state from the given nonce.
    312 // See NIST SP 800-38D, section 7.1. This assumes that counter is filled with
    313 // zeros on entry.
    314 func (g *gcm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) {
    315 	// GCM has two modes of operation with respect to the initial counter
    316 	// state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path"
    317 	// for nonces of other lengths. For a 96-bit nonce, the nonce, along
    318 	// with a four-byte big-endian counter starting at one, is used
    319 	// directly as the starting counter. For other nonce sizes, the counter
    320 	// is computed by passing it through the GHASH function.
    321 	if len(nonce) == gcmStandardNonceSize {
    322 		copy(counter[:], nonce)
    323 		counter[gcmBlockSize-1] = 1
    324 	} else {
    325 		var y gcmFieldElement
    326 		g.update(&y, nonce)
    327 		y.high ^= uint64(len(nonce)) * 8
    328 		g.mul(&y)
    329 		putUint64(counter[:8], y.low)
    330 		putUint64(counter[8:], y.high)
    331 	}
    332 }
    333 
    334 // auth calculates GHASH(ciphertext, additionalData), masks the result with
    335 // tagMask and writes the result to out.
    336 func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) {
    337 	var y gcmFieldElement
    338 	g.update(&y, additionalData)
    339 	g.update(&y, ciphertext)
    340 
    341 	y.low ^= uint64(len(additionalData)) * 8
    342 	y.high ^= uint64(len(ciphertext)) * 8
    343 
    344 	g.mul(&y)
    345 
    346 	putUint64(out, y.low)
    347 	putUint64(out[8:], y.high)
    348 
    349 	xorWords(out, out, tagMask[:])
    350 }
    351 
    352 func getUint64(data []byte) uint64 {
    353 	r := uint64(data[0])<<56 |
    354 		uint64(data[1])<<48 |
    355 		uint64(data[2])<<40 |
    356 		uint64(data[3])<<32 |
    357 		uint64(data[4])<<24 |
    358 		uint64(data[5])<<16 |
    359 		uint64(data[6])<<8 |
    360 		uint64(data[7])
    361 	return r
    362 }
    363 
    364 func putUint64(out []byte, v uint64) {
    365 	out[0] = byte(v >> 56)
    366 	out[1] = byte(v >> 48)
    367 	out[2] = byte(v >> 40)
    368 	out[3] = byte(v >> 32)
    369 	out[4] = byte(v >> 24)
    370 	out[5] = byte(v >> 16)
    371 	out[6] = byte(v >> 8)
    372 	out[7] = byte(v)
    373 }
    374