safing-jess/tools/gostdlib/hmac.go
2020-01-13 00:15:58 +01:00

77 lines
1.6 KiB
Go

package gostdlib
import (
"crypto/hmac"
"errors"
"github.com/safing/jess/tools"
)
func init() {
tools.Register(&tools.Tool{
Info: &tools.ToolInfo{
Name: "HMAC",
Purpose: tools.PurposeMAC,
Options: []uint8{
tools.OptionNeedsDedicatedHasher,
tools.OptionHasState,
},
SecurityLevel: 0, // depends on used hash function
Comment: "RFC 2104, FIPS 198",
Author: "Mihir Bellare et al., 1996",
},
Factory: func() tools.ToolLogic { return &HMAC{} },
})
}
// HMAC implements the cryptographic interface for HMAC message authentication codes.
type HMAC struct {
tools.ToolLogicBase
key []byte
}
// Setup implements the ToolLogic interface.
func (hm *HMAC) Setup() (err error) {
// get key
hm.key, err = hm.Helper().NewSessionKey()
if err != nil {
return err
}
return nil
}
// Reset implements the ToolLogic interface.
func (hm *HMAC) Reset() error {
// clean up key
hm.Helper().Burn(hm.key)
return nil
}
// MAC implements the ToolLogic interface.
func (hm *HMAC) MAC(data, associatedData []byte) ([]byte, error) {
// create MAC
mac := hmac.New(hm.HashTool().New, hm.key)
// write data
n, err := mac.Write(data)
if err != nil {
return nil, err
}
if n != len(data) {
return nil, errors.New("failed to fully write data to HMAC hasher")
}
// write associated data
if len(associatedData) > 0 {
n, err := mac.Write(associatedData)
if err != nil {
return nil, err
}
if n != len(associatedData) {
return nil, errors.New("failed to fully write associated data to HMAC hasher")
}
}
// return sum
return mac.Sum(nil), nil
}