@@ -95,6 +95,7 @@ var signatureAlgorithmMapping = map[apiv1.SignatureAlgorithm]algorithmAttributes
9595// CreateKey methods can create keys with the following URIs:
9696// - mackms:label=my-name
9797// - mackms:label=my-name;tag=com.smallstep.crypto
98+ // - mackms;label=my-name;tag=
9899// - mackms;label=my-name;se=true;bio=true
99100//
100101// GetPublicKey and CreateSigner accepts the above URIs as well as the following
@@ -107,7 +108,8 @@ var signatureAlgorithmMapping = map[apiv1.SignatureAlgorithm]algorithmAttributes
107108// represents the key name. You will be able to see the keys in the Keychain,
108109// looking for the value.
109110// - "tag" corresponds with kSecAttrApplicationTag. It defaults to
110- // com.smallstep.crypto.
111+ // com.smallstep.crypto. If tag is an empty string ("tag="), the attribute
112+ // will not be set.
111113// - "se" is a boolean. If set to true, it will store the key in the
112114// Secure Enclave. This option requires the application to be code-signed
113115// with the appropriate entitlements.
@@ -189,21 +191,22 @@ func (k *MacKMS) CreateKey(req *apiv1.CreateKeyRequest) (*apiv1.CreateKeyRespons
189191 }
190192
191193 // Define key attributes
192- cfTag , err := cf .NewData ([]byte (u .tag ))
193- if err != nil {
194- return nil , fmt .Errorf ("mackms CreateKey failed: %w" , err )
195- }
196- defer cfTag .Release ()
197-
198194 cfLabel , err := cf .NewString (u .label )
199195 if err != nil {
200196 return nil , fmt .Errorf ("mackms CreateKey failed: %w" , err )
201197 }
202198 defer cfLabel .Release ()
203199
204200 keyAttributesDict := cf.Dictionary {
205- security .KSecAttrApplicationTag : cfTag ,
206- security .KSecAttrIsPermanent : cf .True ,
201+ security .KSecAttrIsPermanent : cf .True ,
202+ }
203+ if u .tag != "" {
204+ cfTag , err := cf .NewData ([]byte (u .tag ))
205+ if err != nil {
206+ return nil , fmt .Errorf ("mackms CreateKey failed: %w" , err )
207+ }
208+ defer cfTag .Release ()
209+ keyAttributesDict [security .KSecAttrApplicationTag ] = cfTag
207210 }
208211 if u .useSecureEnclave {
209212 // After the first unlock, the data remains accessible until the next
@@ -491,12 +494,6 @@ func (*MacKMS) DeleteKey(req *apiv1.DeleteKeyRequest) error {
491494 return fmt .Errorf ("mackms DeleteKey failed: %w" , err )
492495 }
493496
494- cfTag , err := cf .NewData ([]byte (u .tag ))
495- if err != nil {
496- return fmt .Errorf ("mackms DeleteKey failed: %w" , err )
497- }
498- defer cfTag .Release ()
499-
500497 cfLabel , err := cf .NewString (u .label )
501498 if err != nil {
502499 return fmt .Errorf ("mackms DeleteKey failed: %w" , err )
@@ -505,10 +502,17 @@ func (*MacKMS) DeleteKey(req *apiv1.DeleteKeyRequest) error {
505502
506503 for _ , keyClass := range []cf.TypeRef {security .KSecAttrKeyClassPublic , security .KSecAttrKeyClassPrivate } {
507504 dict := cf.Dictionary {
508- security .KSecClass : security .KSecClassKey ,
509- security .KSecAttrApplicationTag : cfTag ,
510- security .KSecAttrLabel : cfLabel ,
511- security .KSecAttrKeyClass : keyClass ,
505+ security .KSecClass : security .KSecClassKey ,
506+ security .KSecAttrLabel : cfLabel ,
507+ security .KSecAttrKeyClass : keyClass ,
508+ }
509+ if u .tag != "" {
510+ cfTag , err := cf .NewData ([]byte (u .tag ))
511+ if err != nil {
512+ return fmt .Errorf ("mackms DeleteKey failed: %w" , err )
513+ }
514+ defer cfTag .Release ()
515+ dict [security .KSecAttrApplicationTag ] = cfTag
512516 }
513517 // Extract logic to deleteItem to avoid defer on loops
514518 if err := deleteItem (dict , u .hash ); err != nil {
@@ -672,25 +676,26 @@ func deleteItem(dict cf.Dictionary, hash []byte) error {
672676}
673677
674678func getPrivateKey (u * keyAttributes ) (* security.SecKeyRef , error ) {
675- cfTag , err := cf .NewData ([]byte (u .tag ))
676- if err != nil {
677- return nil , err
678- }
679- defer cfTag .Release ()
680-
681679 cfLabel , err := cf .NewString (u .label )
682680 if err != nil {
683681 return nil , err
684682 }
685683 defer cfLabel .Release ()
686684
687685 dict := cf.Dictionary {
688- security .KSecClass : security .KSecClassKey ,
689- security .KSecAttrApplicationTag : cfTag ,
690- security .KSecAttrLabel : cfLabel ,
691- security .KSecAttrKeyClass : security .KSecAttrKeyClassPrivate ,
692- security .KSecReturnRef : cf .True ,
693- security .KSecMatchLimit : security .KSecMatchLimitOne ,
686+ security .KSecClass : security .KSecClassKey ,
687+ security .KSecAttrLabel : cfLabel ,
688+ security .KSecAttrKeyClass : security .KSecAttrKeyClassPrivate ,
689+ security .KSecReturnRef : cf .True ,
690+ security .KSecMatchLimit : security .KSecMatchLimitOne ,
691+ }
692+ if u .tag != "" {
693+ cfTag , err := cf .NewData ([]byte (u .tag ))
694+ if err != nil {
695+ return nil , err
696+ }
697+ defer cfTag .Release ()
698+ dict [security .KSecAttrApplicationTag ] = cfTag
694699 }
695700 if len (u .hash ) > 0 {
696701 d , err := cf .NewData (u .hash )
@@ -1013,7 +1018,7 @@ func parseURI(rawuri string) (*keyAttributes, error) {
10131018 return nil , fmt .Errorf ("error parsing %q: label is required" , rawuri )
10141019 }
10151020 tag := u .Get ("tag" )
1016- if tag == "" {
1021+ if tag == "" && ! u . Has ( "tag" ) {
10171022 tag = DefaultTag
10181023 }
10191024 return & keyAttributes {
@@ -1100,7 +1105,7 @@ func parseSearchURI(rawuri string) (*keySearchAttributes, error) {
11001105 // mackms:label=my-key;tag=my-tag;hash=010a...;se=true;bio=true
11011106 label := u .Get ("label" ) // when searching, the label can be empty
11021107 tag := u .Get ("tag" )
1103- if tag == "" {
1108+ if tag == "" && ! u . Has ( "tag" ) {
11041109 tag = DefaultTag
11051110 }
11061111 return & keySearchAttributes {
0 commit comments