1// Copyright 2015 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 tea implements the TEA algorithm, as defined in Needham and 6// Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithm”. See 7// http://www.cix.co.uk/~klockstone/tea.pdf for details. 8// 9// TEA is a legacy cipher and its short block size makes it vulnerable to 10// birthday bound attacks (see https://sweet32.info). It should only be used 11// where compatibility with legacy systems, not security, is the goal. 12// 13// Deprecated: any new system should use AES (from crypto/aes, if necessary in 14// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from 15// golang.org/x/crypto/chacha20poly1305). 16package tea 17 18import ( 19 "crypto/cipher" 20 "encoding/binary" 21 "errors" 22) 23 24const ( 25 // BlockSize is the size of a TEA block, in bytes. 26 BlockSize = 8 27 28 // KeySize is the size of a TEA key, in bytes. 29 KeySize = 16 30 31 // delta is the TEA key schedule constant. 32 delta = 0x9e3779b9 33 34 // numRounds is the standard number of rounds in TEA. 35 numRounds = 64 36) 37 38// tea is an instance of the TEA cipher with a particular key. 39type tea struct { 40 key [16]byte 41 rounds int 42} 43 44// NewCipher returns an instance of the TEA cipher with the standard number of 45// rounds. The key argument must be 16 bytes long. 46func NewCipher(key []byte) (cipher.Block, error) { 47 return NewCipherWithRounds(key, numRounds) 48} 49 50// NewCipherWithRounds returns an instance of the TEA cipher with a given 51// number of rounds, which must be even. The key argument must be 16 bytes 52// long. 53func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) { 54 if len(key) != 16 { 55 return nil, errors.New("tea: incorrect key size") 56 } 57 58 if rounds&1 != 0 { 59 return nil, errors.New("tea: odd number of rounds specified") 60 } 61 62 c := &tea{ 63 rounds: rounds, 64 } 65 copy(c.key[:], key) 66 67 return c, nil 68} 69 70// BlockSize returns the TEA block size, which is eight bytes. It is necessary 71// to satisfy the Block interface in the package "crypto/cipher". 72func (*tea) BlockSize() int { 73 return BlockSize 74} 75 76// Encrypt encrypts the 8 byte buffer src using the key in t and stores the 77// result in dst. Note that for amounts of data larger than a block, it is not 78// safe to just call Encrypt on successive blocks; instead, use an encryption 79// mode like CBC (see crypto/cipher/cbc.go). 80func (t *tea) Encrypt(dst, src []byte) { 81 e := binary.BigEndian 82 v0, v1 := e.Uint32(src), e.Uint32(src[4:]) 83 k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) 84 85 sum := uint32(0) 86 delta := uint32(delta) 87 88 for i := 0; i < t.rounds/2; i++ { 89 sum += delta 90 v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) 91 v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) 92 } 93 94 e.PutUint32(dst, v0) 95 e.PutUint32(dst[4:], v1) 96} 97 98// Decrypt decrypts the 8 byte buffer src using the key in t and stores the 99// result in dst. 100func (t *tea) Decrypt(dst, src []byte) { 101 e := binary.BigEndian 102 v0, v1 := e.Uint32(src), e.Uint32(src[4:]) 103 k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) 104 105 delta := uint32(delta) 106 sum := delta * uint32(t.rounds/2) // in general, sum = delta * n 107 108 for i := 0; i < t.rounds/2; i++ { 109 v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) 110 v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) 111 sum -= delta 112 } 113 114 e.PutUint32(dst, v0) 115 e.PutUint32(dst[4:], v1) 116} 117