github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/morus/morus.go (about) 1 // morus.go - High-level interface 2 // 3 // To the extent possible under law, Yawning Angel has waived all copyright 4 // and related or neighboring rights to the software, using the Creative 5 // Commons "CC0" public domain dedication. See LICENSE or 6 // <http://creativecommons.org/publicdomain/zero/1.0/> for full details. 7 8 // Package morus implements the MORUS-1280-256 Authenticated Cipher. 9 // 10 // This implementation is derived from the reference implementation by 11 // Hongjun Wu and Tao Huang. 12 package morus 13 14 import ( 15 "encoding/binary" 16 "errors" 17 ) 18 19 const ( 20 // KeySize is the size of a key in bytes. 21 KeySize = 32 22 23 // NonceSize is the size of a nonce in bytes. 24 NonceSize = 16 25 26 // TagSize is the size of an authentication tag in bytes. 27 TagSize = 16 28 29 // Version is the version of the MORUS specification implemented. 30 Version = "2.0" 31 ) 32 33 var ( 34 // ErrInvalidKeySize is the error thrown via a panic when a key is an 35 // invalid size. 36 ErrInvalidKeySize = errors.New("morus: invalid key size") 37 38 // ErrInvalidNonceSize is the error thrown via a panic when a nonce is 39 // an invalid size. 40 ErrInvalidNonceSize = errors.New("morus: invalid nonce size") 41 42 // ErrOpen is the error returned when the message authentication fails 43 // during an Open call. 44 ErrOpen = errors.New("morus: message authentication failed") 45 46 rawInitializationConstant = [32]byte{ 47 0x0, 0x1, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d, 48 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62, 49 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1, 50 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd, 51 } 52 initializationConstants [4]uint64 53 54 // Neither the specification document nor the portable reference 55 // implementations define how this should be handled. However the 56 // AVX2 implementation isn't byte swapping, so it's likely safe to 57 // assume little endian. 58 byteOrder = binary.LittleEndian 59 ) 60 61 // AEAD is a MORUS instance, implementing crypto/cipher.AEAD. 62 type AEAD struct { 63 key []byte 64 } 65 66 // NonceSize returns the size of the nonce that must be passed to Seal and 67 // Open. 68 func (ae *AEAD) NonceSize() int { 69 return NonceSize 70 } 71 72 // Overhead returns the maximum difference between the lengths of a plaintext 73 // and its ciphertext. 74 func (ae *AEAD) Overhead() int { 75 return TagSize 76 } 77 78 // Seal encrypts and authenticates plaintext, authenticates the 79 // additional data and appends the result to dst, returning the updated 80 // slice. The nonce must be NonceSize() bytes long and unique for all 81 // time, for a given key. 82 // 83 // The plaintext and dst must overlap exactly or not at all. To reuse 84 // plaintext's storage for the encrypted output, use plaintext[:0] as dst. 85 func (ae *AEAD) Seal(dst, nonce, plaintext, additionalData []byte) []byte { 86 if len(nonce) != NonceSize { 87 panic(ErrInvalidNonceSize) 88 } 89 dst = hardwareAccelImpl.aeadEncryptFn(dst, plaintext, additionalData, nonce, ae.key) 90 return dst 91 } 92 93 // Open decrypts and authenticates ciphertext, authenticates the 94 // additional data and, if successful, appends the resulting plaintext 95 // to dst, returning the updated slice. The nonce must be NonceSize() 96 // bytes long and both it and the additional data must match the 97 // value passed to Seal. 98 // 99 // The ciphertext and dst must overlap exactly or not at all. To reuse 100 // ciphertext's storage for the decrypted output, use ciphertext[:0] as dst. 101 // 102 // Even if the function fails, the contents of dst, up to its capacity, 103 // may be overwritten. 104 func (ae *AEAD) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { 105 var err error 106 var ok bool 107 108 if len(nonce) != NonceSize { 109 panic(ErrInvalidNonceSize) 110 } 111 dst, ok = hardwareAccelImpl.aeadDecryptFn(dst, ciphertext, additionalData, nonce, ae.key) 112 if !ok { 113 err = ErrOpen 114 } 115 return dst, err 116 } 117 118 // Reset securely purges stored sensitive data from the AEAD instance. 119 func (ae *AEAD) Reset() { 120 burnBytes(ae.key) 121 } 122 123 // New returns a new keyed MORUS-1280-256 instance. 124 func New(key []byte) *AEAD { 125 if len(key) != KeySize { 126 panic(ErrInvalidKeySize) 127 } 128 return &AEAD{key: append([]byte{}, key...)} 129 } 130 131 // Shamelessly stolen from the Go runtime library. 132 func sliceForAppend(in []byte, n int) (head, tail []byte) { 133 if total := len(in) + n; cap(in) >= total { 134 head = in[:total] 135 } else { 136 head = make([]byte, total) 137 copy(head, in) 138 } 139 tail = head[len(in):] 140 return 141 } 142 143 func init() { 144 initializationConstants[0] = byteOrder.Uint64(rawInitializationConstant[0:]) 145 initializationConstants[1] = byteOrder.Uint64(rawInitializationConstant[8:]) 146 initializationConstants[2] = byteOrder.Uint64(rawInitializationConstant[16:]) 147 initializationConstants[3] = byteOrder.Uint64(rawInitializationConstant[24:]) 148 }