safing-jess/tools/tool.go
2021-10-02 23:00:01 +02:00

190 lines
5.8 KiB
Go

package tools
import "strings"
// Tool describes a cryptographic tool and is split into information and logic parts.
type Tool struct {
// Info is a globally shared instance of generic tool information.
Info *ToolInfo
// StaticLogic holds a static (and possibly even nil) value of the tool logic in order to access certain handling methods.
StaticLogic ToolLogic
// Factory returns an initialized (but not yet set up) instance of ToolLogic.
// Setup is done after initialization by overriding Setup().
Factory func() ToolLogic
}
// ToolInfo holds generic information about a tool.
type ToolInfo struct {
Name string
Purpose uint8
Options []uint8
KeySize int // in bytes
NonceSize int // in bytes
SecurityLevel int // approx. attack complexity as 2^n
Comment string
Author string
}
// Tool Purposes.
const (
// Key Management and Creation, as well as Authenticity.
// PurposeKeyDerivation declares key derivation capabilities.
PurposeKeyDerivation uint8 = iota + 1
// PurposePassDerivation declares password derivation capabilties (make a secure key out of a password).
// Provides SenderAuthentication, ReceiverAuthentication requirements.
PurposePassDerivation
// PurposeKeyExchange declares (DH-style) key exchange capabilities.
// A trusted key of the receiver must be supplied.
// Provides ReceiverAuthentication attribute.
PurposeKeyExchange
// PurposeKeyEncapsulation declares key encapsulation capabilities (key is encrypted with the receivers public key)
// A trusted key of the receiver must be supplied.
// Provides ReceiverAuthentication attribute.
PurposeKeyEncapsulation
// PurposeSigning declares signing capabilities.
// The receiver must already have the public key.
// Provides SenderAuthentication attribute. Theoretically also provides integrity, but as signing is done after everything else, it will not be able to detect a wrong key during decryption.
PurposeSigning
// Confidentiality and Integrity.
// PurposeIntegratedCipher declares that the tool provides both encryption and integrity verification capabilities.
// Provies Confidentiality and Integrity requirements.
PurposeIntegratedCipher
// PurposeCipher declares that the tool provides encryption capabilities.
// Provies Confidentiality attribute.
PurposeCipher
// PurposeMAC declares that the tool provides integrity verification capabilities.
// Provies Integrity attribute.
PurposeMAC
)
// Tool Options.
const (
// Operation Types.
// OptionStreaming declares that the tool can work with streaming data and might be given a io.Reader and io.Writer instead of just a []byte slice.
// TODO: Implementation pending.
OptionStreaming uint8 = iota + 1
// Needs.
// OptionNeedsManagedHasher declares that the tool requires a hashing algorithm to work. It will automatically hash everything that needs to be authenticated and may be shared with other algorithms.
OptionNeedsManagedHasher
// OptionNeedsDedicatedHasher declares that the tool requires a hashing algorithm to work. It will get its own instance and will have to do all the work itself.
OptionNeedsDedicatedHasher
// OptionNeedsSecurityLevel declares that the tool requires a specified security level. This will be derived from the rest of the used tools, or must be specified by the user directly.
OptionNeedsSecurityLevel
// OptionNeedsDefaultKeySize declares that the tool requires a default key size for operation. This will be derived from the rest of the used tools, or must be specified by the user directly.
OptionNeedsDefaultKeySize
// OptionHasState declares that the tool has an internal state and requires the setup and reset routines to be run before/after usage. KeyDerivation tools do not have to declare this, their state is handled separately.
OptionHasState
)
// HasOption returns whether the *ToolInfo has the given option.
func (ti *ToolInfo) HasOption(option uint8) bool {
for _, optionEntry := range ti.Options {
if option == optionEntry {
return true
}
}
return false
}
// With uses the original ToolInfo as a template for a new ToolInfo and returns the new ToolInfo.
func (ti *ToolInfo) With(changes *ToolInfo) *ToolInfo {
if changes.Name == "" {
changes.Name = ti.Name
}
if changes.Purpose == 0 {
changes.Purpose = ti.Purpose
}
if len(changes.Options) == 0 {
changes.Options = ti.Options
}
if changes.KeySize == 0 {
changes.KeySize = ti.KeySize
}
if changes.NonceSize == 0 {
changes.NonceSize = ti.NonceSize
}
if changes.SecurityLevel == 0 {
changes.SecurityLevel = ti.SecurityLevel
}
if changes.Comment == "" {
changes.Comment = ti.Comment
}
if changes.Author == "" {
changes.Author = ti.Author
}
return changes
}
// FormatPurpose returns the name of the declared purpose.
func (ti *ToolInfo) FormatPurpose() string {
switch ti.Purpose {
case PurposeKeyDerivation:
return "KeyDerivation"
case PurposePassDerivation:
return "PassDerivation"
case PurposeKeyExchange:
return "KeyExchange"
case PurposeKeyEncapsulation:
return "KeyEncapsulation"
case PurposeSigning:
return "Signing"
case PurposeIntegratedCipher:
return "IntegratedCipher"
case PurposeCipher:
return "Cipher"
case PurposeMAC:
return "MAC"
default:
return "UNKNOWN"
}
}
// FormatOptions returns a list of names of the declared options.
func (ti *ToolInfo) FormatOptions() string {
if len(ti.Options) == 0 {
return ""
}
var s []string
for _, optionID := range ti.Options {
switch optionID {
case OptionStreaming:
s = append(s, "Streaming")
case OptionNeedsManagedHasher:
s = append(s, "NeedsManagedHasher")
case OptionNeedsDedicatedHasher:
s = append(s, "NeedsDedicatedHasher")
case OptionNeedsSecurityLevel:
s = append(s, "NeedsSecurityLevel")
case OptionNeedsDefaultKeySize:
s = append(s, "NeedsDefaultKeySize")
case OptionHasState:
s = append(s, "HasState")
default:
s = append(s, "UNKNOWN")
}
}
return strings.Join(s, ", ")
}