package cose

import (
	"crypto"
	"hash"
	"strconv"
)

// Algorithms supported by this library.
//
// When using an algorithm which requires hashing,
// make sure the associated hash function is linked to the binary.
const (
	// RSASSA-PSS w/ SHA-256 by RFC 8230.
	// Requires an available crypto.SHA256.
	AlgorithmPS256 Algorithm = -37

	// RSASSA-PSS w/ SHA-384 by RFC 8230.
	// Requires an available crypto.SHA384.
	AlgorithmPS384 Algorithm = -38

	// RSASSA-PSS w/ SHA-512 by RFC 8230.
	// Requires an available crypto.SHA512.
	AlgorithmPS512 Algorithm = -39

	// ECDSA w/ SHA-256 by RFC 8152.
	// Requires an available crypto.SHA256.
	AlgorithmES256 Algorithm = -7

	// ECDSA w/ SHA-384 by RFC 8152.
	// Requires an available crypto.SHA384.
	AlgorithmES384 Algorithm = -35

	// ECDSA w/ SHA-512 by RFC 8152.
	// Requires an available crypto.SHA512.
	AlgorithmES512 Algorithm = -36

	// PureEdDSA by RFC 8152.
	AlgorithmEd25519 Algorithm = -8
)

// Algorithm represents an IANA algorithm entry in the COSE Algorithms registry.
// Algorithms with string values are not supported.
//
// # See Also
//
// COSE Algorithms: https://www.iana.org/assignments/cose/cose.xhtml#algorithms
//
// RFC 8152 16.4: https://datatracker.ietf.org/doc/html/rfc8152#section-16.4
type Algorithm int64

// extAlgorithm describes an extended algorithm, which is not implemented this
// library.
type extAlgorithm struct {
	// Name of the algorithm.
	Name string

	// Hash is the hash algorithm associated with the algorithm.
	// If HashFunc presents, Hash is ignored.
	// If HashFunc does not present and Hash is set to 0, no hash is used.
	Hash crypto.Hash

	// HashFunc is the hash algorithm associated with the algorithm.
	// HashFunc is preferred in the case that the hash algorithm is not
	// supported by the golang build-in crypto hashes.
	// For regular scenarios, use Hash instead.
	HashFunc func() hash.Hash
}

// extAlgorithms contains extended algorithms.
var extAlgorithms map[Algorithm]extAlgorithm

// String returns the name of the algorithm
func (a Algorithm) String() string {
	switch a {
	case AlgorithmPS256:
		return "PS256"
	case AlgorithmPS384:
		return "PS384"
	case AlgorithmPS512:
		return "PS512"
	case AlgorithmES256:
		return "ES256"
	case AlgorithmES384:
		return "ES384"
	case AlgorithmES512:
		return "ES512"
	case AlgorithmEd25519:
		// As stated in RFC 8152 8.2, only the pure EdDSA version is used for
		// COSE.
		return "EdDSA"
	}
	if alg, ok := extAlgorithms[a]; ok {
		return alg.Name
	}
	return "unknown algorithm value " + strconv.Itoa(int(a))
}

// hashFunc returns the hash associated with the algorithm supported by this
// library.
func (a Algorithm) hashFunc() (crypto.Hash, bool) {
	switch a {
	case AlgorithmPS256, AlgorithmES256:
		return crypto.SHA256, true
	case AlgorithmPS384, AlgorithmES384:
		return crypto.SHA384, true
	case AlgorithmPS512, AlgorithmES512:
		return crypto.SHA512, true
	case AlgorithmEd25519:
		return 0, true
	}
	return 0, false
}

// newHash returns a new hash instance for computing the digest specified in the
// algorithm.
// Returns nil if no hash is required for the message.
func (a Algorithm) newHash() (hash.Hash, error) {
	h, ok := a.hashFunc()
	if !ok {
		alg, ok := extAlgorithms[a]
		if !ok {
			return nil, ErrUnknownAlgorithm
		}
		if alg.HashFunc != nil {
			return alg.HashFunc(), nil
		}
		h = alg.Hash
	}
	if h == 0 {
		// no hash required
		return nil, nil
	}
	if h.Available() {
		return h.New(), nil
	}
	return nil, ErrUnavailableHashFunc
}

// computeHash computing the digest using the hash specified in the algorithm.
// Returns the input data if no hash is required for the message.
func (a Algorithm) computeHash(data []byte) ([]byte, error) {
	h, err := a.newHash()
	if err != nil {
		return nil, err
	}
	if h == nil {
		return data, nil
	}
	if _, err := h.Write(data); err != nil {
		return nil, err
	}
	return h.Sum(nil), nil
}

// RegisterAlgorithm provides extensibility for the cose library to support
// private algorithms or algorithms not yet registered in IANA.
// The existing algorithms cannot be re-registered.
// The parameter `hash` is the hash algorithm associated with the algorithm. If
// hashFunc presents, hash is ignored. If hashFunc does not present and hash is
// set to 0, no hash is used for this algorithm.
// The parameter `hashFunc` is preferred in the case that the hash algorithm is not
// supported by the golang build-in crypto hashes.
func RegisterAlgorithm(alg Algorithm, name string, hash crypto.Hash, hashFunc func() hash.Hash) error {
	if _, ok := alg.hashFunc(); ok {
		return ErrAlgorithmRegistered
	}
	if _, ok := extAlgorithms[alg]; ok {
		return ErrAlgorithmRegistered
	}
	if extAlgorithms == nil {
		extAlgorithms = make(map[Algorithm]extAlgorithm)
	}
	extAlgorithms[alg] = extAlgorithm{
		Name:     name,
		Hash:     hash,
		HashFunc: hashFunc,
	}
	return nil
}
