image: Functions to search protected TLVs

This commit adds two sets of functions to the `image.Image` struct:

    <verb>ProtTlvs<...>: Operates on protected TLVs only.
    <verb>AllTlvs<...>: Operates on regulare and protected TLVs.
diff --git a/image/image.go b/image/image.go
index eb571eb..7cd1e1a 100644
--- a/image/image.go
+++ b/image/image.go
@@ -313,7 +313,125 @@
 	})
 }
 
-// ProtTrailer constructs a protected ImageTrailer corresponding to the given image.
+// FindProtTlvIndicesIf searches an image for TLVs satisfying the given
+// predicate and returns their indices.
+func (img *Image) FindProtTlvIndicesIf(pred func(tlv ImageTlv) bool) []int {
+	var idxs []int
+
+	for i, tlv := range img.ProtTlvs {
+		if pred(tlv) {
+			idxs = append(idxs, i)
+		}
+	}
+
+	return idxs
+}
+
+// FindProtTlvIndices searches an image for TLVs of the specified type and
+// returns their indices.
+func (img *Image) FindProtTlvIndices(tlvType uint8) []int {
+	return img.FindProtTlvIndicesIf(func(tlv ImageTlv) bool {
+		return tlv.Header.Type == tlvType
+	})
+}
+
+// FindTlvIndices searches an image for TLVs satisfying the given predicate and
+// returns them.
+func (img *Image) FindProtTlvsIf(pred func(tlv ImageTlv) bool) []*ImageTlv {
+	var tlvs []*ImageTlv
+
+	idxs := img.FindProtTlvIndicesIf(pred)
+	for _, idx := range idxs {
+		tlvs = append(tlvs, &img.Tlvs[idx])
+	}
+
+	return tlvs
+}
+
+// FindProtTlvs retrieves all TLVs in an image's footer with the specified type.
+func (img *Image) FindProtTlvs(tlvType uint8) []*ImageTlv {
+	var tlvs []*ImageTlv
+
+	idxs := img.FindProtTlvIndices(tlvType)
+	for _, idx := range idxs {
+		tlvs = append(tlvs, &img.Tlvs[idx])
+	}
+
+	return tlvs
+}
+
+// FindProtUniqueTlv retrieves a TLV in an image's footer with the specified
+// type.  It returns an error if there is more than one TLV with this type.
+func (i *Image) FindProtUniqueTlv(tlvType uint8) (*ImageTlv, error) {
+	tlvs := i.FindProtTlvs(tlvType)
+	if len(tlvs) == 0 {
+		return nil, nil
+	}
+	if len(tlvs) > 1 {
+		return nil, errors.Errorf("image contains %d TLVs with type %d",
+			len(tlvs), tlvType)
+	}
+
+	return tlvs[0], nil
+}
+
+// RemoveProtTlvsIf removes all TLVs from an image that satisfy the supplied
+// predicate.  It returns a slice of the removed TLVs.
+func (i *Image) RemoveProtTlvsIf(pred func(tlv ImageTlv) bool) []ImageTlv {
+	rmed := []ImageTlv{}
+
+	for idx := 0; idx < len(i.ProtTlvs); {
+		tlv := i.ProtTlvs[idx]
+		if pred(tlv) {
+			rmed = append(rmed, tlv)
+			i.ProtTlvs = append(i.ProtTlvs[:idx], i.ProtTlvs[idx+1:]...)
+		} else {
+			idx++
+		}
+	}
+
+	return rmed
+}
+
+// RemoveProtTlvsWithType removes from an image all TLVs with the specified
+// type.  It returns a slice of the removed TLVs.
+func (i *Image) RemoveProtTlvsWithType(tlvType uint8) []ImageTlv {
+	return i.RemoveProtTlvsIf(func(tlv ImageTlv) bool {
+		return tlv.Header.Type == tlvType
+	})
+}
+
+func (i *Image) FindAllTlvsIf(pred func(tlv ImageTlv) bool) []*ImageTlv {
+	regTlvs := i.FindTlvsIf(pred)
+	protTlvs := i.FindProtTlvsIf(pred)
+
+	return append(regTlvs, protTlvs...)
+}
+
+func (i *Image) FindAllTlvs(tlvType uint8) []*ImageTlv {
+	return i.FindAllTlvsIf(func(tlv ImageTlv) bool {
+		return tlv.Header.Type == tlvType
+	})
+}
+
+func (i *Image) FindAllUniqueTlv(tlvType uint8) (*ImageTlv, error) {
+	tlvs := i.FindAllTlvs(tlvType)
+
+	if len(tlvs) == 0 {
+		return nil, nil
+	}
+
+	if len(tlvs) > 1 {
+		return nil, errors.Errorf(
+			"image contains too many TLVs with type %d: have=%d want<=1",
+			tlvType, len(tlvs))
+	}
+
+	return tlvs[0], nil
+}
+
+// ProtTrailer constructs a protected ImageTrailer corresponding to the given
+// image.
 func (img *Image) ProtTrailer() ImageTrailer {
 	trailer := ImageTrailer{
 		Magic:     IMAGE_PROT_TRAILER_MAGIC,