package p11 import ( "errors" "github.com/miekg/pkcs11" ) // ErrAttributeNotFound is returned by Attrbibute() if the searched attribute isn't found. var ErrAttributeNotFound = errors.New("attribute not found") // ErrTooManyAttributesFound is returned by Attrbibute() if the search returned multiple attributes. var ErrTooManyAttributesFound = errors.New("too many attributes found") // Object represents a handle to a PKCS#11 object. It is attached to the // session used to find it. Once that session is closed, operations on the // Object will fail. Operations may also depend on the logged-in state of // the application. type Object struct { session *sessionImpl objectHandle pkcs11.ObjectHandle } // Label returns the label of an object. func (o Object) Label() (string, error) { labelBytes, err := o.Attribute(pkcs11.CKA_LABEL) if err != nil { return "", err } return string(labelBytes), nil } // Value returns an object's CKA_VALUE attribute, as bytes. func (o Object) Value() ([]byte, error) { return o.Attribute(pkcs11.CKA_VALUE) } // Attribute gets exactly one attribute from a PKCS#11 object, returning // an error if the attribute is not found, or if multiple attributes are // returned. On success, it will return the value of that attribute as a slice // of bytes. For attributes not present (i.e. CKR_ATTRIBUTE_TYPE_INVALID), // Attribute returns a nil slice and nil error. func (o Object) Attribute(attributeType uint) ([]byte, error) { o.session.Lock() defer o.session.Unlock() attrs, err := o.session.ctx.GetAttributeValue(o.session.handle, o.objectHandle, []*pkcs11.Attribute{pkcs11.NewAttribute(attributeType, nil)}) // The PKCS#11 spec states that C_GetAttributeValue may return // CKR_ATTRIBUTE_TYPE_INVALID if an object simply does not posses a given // attribute. We don't consider that an error, we just consider that // equivalent to an empty value. if err == pkcs11.Error(pkcs11.CKR_ATTRIBUTE_TYPE_INVALID) { return nil, nil } else if err != nil { return nil, err } if len(attrs) == 0 { return nil, ErrAttributeNotFound } if len(attrs) > 1 { return nil, ErrTooManyAttributesFound } return attrs[0].Value, nil } // Set sets exactly one attribute on this object. func (o Object) Set(attributeType uint, value []byte) error { o.session.Lock() defer o.session.Unlock() err := o.session.ctx.SetAttributeValue(o.session.handle, o.objectHandle, []*pkcs11.Attribute{pkcs11.NewAttribute(attributeType, value)}) if err != nil { return err } return nil } // Copy makes a copy of this object, with the attributes in template applied on // top of it, if possible. func (o Object) Copy(template []*pkcs11.Attribute) (Object, error) { s := o.session s.Lock() defer s.Unlock() newHandle, err := s.ctx.CopyObject(s.handle, o.objectHandle, template) if err != nil { return Object{}, err } return Object{ session: s, objectHandle: newHandle, }, nil } // Destroy destroys this object. func (o Object) Destroy() error { s := o.session s.Lock() defer s.Unlock() return s.ctx.DestroyObject(s.handle, o.objectHandle) }