web-dev-qa-db-fra.com

Qu'est-ce qui rend un élément de trousseau unique (dans iOS)?

Ma question concerne les porte-clés sous iOS (iPhone, iPad, ...). Je pense (mais je ne suis pas sûr) que la mise en œuvre des trousseaux sous Mac OS X soulève la même question avec la même réponse.


iOS propose cinq types (classes) d'éléments de trousseau. Vous devez choisir l'une de ces cinq valeurs pour la clé kSecClass pour déterminer le type:

kSecClassGenericPassword  used to store a generic password
kSecClassInternetPassword used to store an internet password
kSecClassCertificate      used to store a certificate
kSecClassKey              used to store a kryptographic key
kSecClassIdentity         used to store an identity (certificate + private key)

Après avoir longtemps lu la documentation sur les pommes, les blogs et les entrées de forum, j'ai découvert qu'un élément de trousseau de type kSecClassGenericPassword tire son caractère unique des attributs kSecAttrAccessGroup, kSecAttrAccount et kSecAttrService.

Si ces trois attributs dans la demande 1 sont les mêmes que dans la demande 2, vous recevez le même élément de trousseau de mot de passe générique, quels que soient les autres attributs. Si un (ou deux ou tous) de ces attributs change sa valeur, alors vous obtenez différents éléments.

Mais kSecAttrService n'est disponible que pour les éléments de type kSecClassGenericPassword, il ne peut donc pas faire partie de la "clé unique" d'un élément de tout autre type, et il ne semble pas y avoir de documentation qui indique clairement quels attributs déterminent de manière unique un élément de trousseau.

L'exemple de code de la classe "KeychainItemWrapper" de "GenericKeychain" utilise l'attribut kSecAttrGeneric pour rendre un élément unique, mais il s'agit d'un bogue. Les deux entrées de cet exemple uniquement sont stockées en tant que deux entrées distinctes, car leur kSecAttrAccessGroup est différent (l'un a le groupe d'accès défini, l'autre le laisse libre). Si vous essayez d'ajouter un deuxième mot de passe sans groupe d'accès, en utilisant KeychainItemWrapper d'Apple, vous échouerez.

Alors, s'il vous plaît, répondez à mes questions:

  • Est-il vrai que la combinaison de kSecAttrAccessGroup, kSecAttrAccount et kSecAttrService est la "clé unique" d'un élément de trousseau dont la kSecClass est kSecClassGenericPassword?
  • Quels attributs rendent un élément de trousseau unique si son kSecClass n'est pas kSecClassGenericPassword?
92
Hubert Schölnast

Les clés primaires sont les suivantes (dérivées de fichiers open source d'Apple, voir Schema.m4 , KeySchema.m4 et SecItem.cpp ):

  • Pour un élément de trousseau de classe kSecClassGenericPassword, la clé primaire est la combinaison de kSecAttrAccount et kSecAttrService.
  • Pour un élément de trousseau de classe kSecClassInternetPassword, la clé primaire est la combinaison de kSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, kSecAttrPort et kSecAttrPath.
  • Pour un élément de trousseau de classe kSecClassCertificate, la clé primaire est la combinaison de kSecAttrCertificateType, kSecAttrIssuer et kSecAttrSerialNumber.
  • Pour un élément de trousseau de classe kSecClassKey, la clé primaire est la combinaison de kSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeyType, kSecAttrKeySizeInBits, kSecAttrEffectiveKeySize, et le créateur, la date de début et la date de fin qui ne sont pas encore exposées par SecItem.
  • Pour un élément de trousseau de classe kSecClassIdentity Je n'ai pas trouvé d'informations sur les champs de clé primaire dans les fichiers open source, mais comme une identité est la combinaison d'une clé privée et d'un certificat, je suppose que la clé primaire est la combinaison des champs de clé primaire pour kSecClassKey et kSecClassCertificate.

Comme chaque élément de trousseau appartient à un groupe d'accès au trousseau, il semble que le groupe d'accès au trousseau (champ kSecAttrAccessGroup) est un champ ajouté à toutes ces clés primaires.

156
Tammo Freese

L'autre jour (sur iOS 7.1), je rencontrais un bug lié à cette question. J'utilisais SecItemCopyMatching pour lire un élément kSecClassGenericPassword et il ne cessait de renvoyer errSecItemNotFound (-25300) même si kSecAttrAccessGroup, kSecAttrAccount et kSecAttrService correspondaient tous à l'élément du trousseau.

Finalement, j'ai compris que kSecAttrAccessible ne correspondait pas. La valeur du trousseau contenait pdmn = dk (kSecAttrAccessibleAlways), mais j'utilisais kSecAttrAccessibleWhenUnlocked.

Bien sûr, cette valeur n'est pas nécessaire en premier lieu pour SecItemCopyMatching, mais le OSStatus n'était pas errSecParam ni errSecBadReq mais juste errSecItemNotFound (-25300) ce qui le rendait un peu difficile à trouver.

Pour SecItemUpdate, j'ai rencontré le même problème, mais dans cette méthode, même l'utilisation du même kSecAttrAccessible dans le paramètre query n'a pas fonctionné. La suppression complète de cet attribut ne l'a corrigé.

J'espère que ce commentaire sauvera quelques précieux moments de débogage pour certains d'entre vous.

8
izik lisbon

La réponse donnée par @Tammo Freese semble être correcte (mais sans mentionner toutes les clés primaires). Je cherchais des preuves dans la documentation. Finalement trouvé:

Documentation Apple mentionnant les clés primaires pour chaque classe de secret (citation ci-dessous):

Le système considère qu'un élément est un doublon pour un trousseau donné lorsque ce trousseau a déjà un élément de la même classe avec le même ensemble de clés primaires composites. Chaque classe d'élément de trousseau a un ensemble différent de clés primaires, bien que quelques attributs soient utilisés en commun dans toutes les classes. En particulier, le cas échéant, kSecAttrSynchronizable et kSecAttrAccessGroup font partie de l'ensemble de clés primaires. Les clés primaires supplémentaires par classe sont répertoriées ci-dessous:

  • Pour les mots de passe génériques, les clés primaires incluent kSecAttrAccount et kSecAttrService.
  • Pour les mots de passe Internet, les clés primaires incluent kSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, kSecAttrPort et kSecAttrPath.
  • Pour les certificats, les clés primaires incluent kSecAttrCertificateType, kSecAttrIssuer et kSecAttrSerialNumber.
  • Pour les éléments clés, les clés primaires incluent kSecAttrKeyClass, kSecAttrKeyType, kSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeySizeInBits et kSecAttrEffectiveKeySize.
  • Pour les éléments d'identité, qui sont un certificat et une clé privée regroupés, les clés primaires sont les mêmes que pour un certificat. Parce qu'une clé privée peut être certifiée plusieurs fois, l'unicité de la certificat détermine celui de l'identité.
2
Julian Król