1// Copyright 2019 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// +build ppc64le,!gccgo,!appengine 6 7package poly1305 8 9//go:noescape 10func initialize(state *[7]uint64, key *[32]byte) 11 12//go:noescape 13func update(state *[7]uint64, msg []byte) 14 15//go:noescape 16func finalize(tag *[TagSize]byte, state *[7]uint64) 17 18// Sum generates an authenticator for m using a one-time key and puts the 19// 16-byte result into out. Authenticating two different messages with the same 20// key allows an attacker to forge messages at will. 21func Sum(out *[16]byte, m []byte, key *[32]byte) { 22 h := newMAC(key) 23 h.Write(m) 24 h.Sum(out) 25} 26 27func newMAC(key *[32]byte) (h mac) { 28 initialize(&h.state, key) 29 return 30} 31 32type mac struct { 33 state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 } 34 35 buffer [TagSize]byte 36 offset int 37} 38 39func (h *mac) Write(p []byte) (n int, err error) { 40 n = len(p) 41 if h.offset > 0 { 42 remaining := TagSize - h.offset 43 if n < remaining { 44 h.offset += copy(h.buffer[h.offset:], p) 45 return n, nil 46 } 47 copy(h.buffer[h.offset:], p[:remaining]) 48 p = p[remaining:] 49 h.offset = 0 50 update(&h.state, h.buffer[:]) 51 } 52 if nn := len(p) - (len(p) % TagSize); nn > 0 { 53 update(&h.state, p[:nn]) 54 p = p[nn:] 55 } 56 if len(p) > 0 { 57 h.offset += copy(h.buffer[h.offset:], p) 58 } 59 return n, nil 60} 61 62func (h *mac) Sum(out *[16]byte) { 63 state := h.state 64 if h.offset > 0 { 65 update(&state, h.buffer[:h.offset]) 66 } 67 finalize(out, &state) 68} 69