Hi Quinn,
This just keeps getting weirder and weirder. I found another post you had made (https://developer.apple.com/forums/thread/69642) that states to set the public key hash into the private key kSecAttrLabel and kSecAttrApplicationLabel (which is weird since the kSecAttrLabel is expected to be text), and into kSecAttrPublicKeyHash in the certificate. In other Apple docs you pointed to it is stated that the kSecAttrPublicKeyHash attribute is read only, which is what was throwing me off.
Once I set that in the SecItemAdd dictionary for the cert, then it seems to associate correctly. So to experiment I found that SecItemCopyMatching with kSecClassCertificate, kSecReturnAttributes and kSecMatchLimitAll returns lots of certificates, almost all of which have many attributes set, e.g. class, cenc, ctyp, subj, issr, labl, pkhh, slnr, etc. In my case I wasn't specifying these, assuming the OS would set them, and my cert just reported a minimal set: class = cert, ctyp = 0, pkhh = {length = 20, bytes = 0x8a95...c955}. Then I went to my dictionary and started adding the others, like cenc, ctyp, subj, etc, but then I got error -67866 = errSecFieldSpecifiedMultiple (Too many fields were specified). I started taking some off, and it seems some attributes always give me that error, like ctyp, issr, srln. I can set the cenc, subj, labl and pkhh ok, but that's about it.
And then when I go to import the intermediate, setting the same set of attributes (but different values from the leaf cert for the labl, subject and pkhh), I get errSecDuplicateItem. Your pointers mention setting kSecAttrApplicationLabel and I've tried making that unique for the leaf and intermediate, but no effect; I don't see why it's indicating duplicate. Here are the results of querying after adding; the intermediate is the result only after I delete the leaf right before adding it in order to get it to add.
Printing description of ((__NSDictionaryM *)0x0000600000227780):
{
cenc = 3;
class = cert;
ctyp = 0;
labl = "Leaf Certificate";
pkhh = {length = 20, bytes = 0xec127a9329e63d6733672bbb40aaecafd091ec79};
subj = {length = 84, bytes = 0x30523150 304e0603 5504030c 4775726e ... 62754861 6a706145 };
}
Printing description of ((__NSDictionaryM *)0x000060000023a400):
{
cenc = 3;
class = cert;
ctyp = 0;
labl = "Intermediate Certificate";
pkhh = {length = 20, bytes = 0x1b73c2a805958e4698d7607b66b23a080f94703e};
subj = {length = 54, bytes = 0x30343132 30300603 5504030c 29444556 ... 4570686d 6572616c };
}
Note that all of this is using the file-based keychain and currently in user space.