1/*
2 * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24//
25// Identity.cpp - Working with Identities
26//
27#include <security_keychain/Identity.h>
28
29#include <security_cdsa_utilities/KeySchema.h>
30#include <security_keychain/KCCursor.h>
31#include <string.h>
32
33using namespace KeychainCore;
34
35Identity::Identity(const SecPointer<KeyItem> &privateKey,
36		const SecPointer<Certificate> &certificate) :
37	mPrivateKey(privateKey),
38	mCertificate(certificate)
39{
40}
41
42Identity::Identity(const StorageManager::KeychainList &keychains, const SecPointer<Certificate> &certificate) :
43	mCertificate(certificate)
44{
45	// Find a key whose label matches the publicKeyHash of the public key in the certificate.
46	KCCursor keyCursor(keychains, CSSM_DL_DB_RECORD_PRIVATE_KEY, NULL);
47	keyCursor->add(CSSM_DB_EQUAL, KeySchema::Label, certificate->publicKeyHash());
48
49	Item key;
50	if (!keyCursor->next(key))
51		MacOSError::throwMe(errSecItemNotFound);
52
53	SecPointer<KeyItem> keyItem(static_cast<KeyItem *>(&*key));
54	mPrivateKey = keyItem;
55}
56
57Identity::~Identity() throw()
58{
59}
60
61SecPointer<KeyItem>
62Identity::privateKey() const
63{
64	return mPrivateKey;
65}
66
67SecPointer<Certificate>
68Identity::certificate() const
69{
70	return mCertificate;
71}
72
73bool
74Identity::operator < (const Identity &other) const
75{
76	// Certificates in different keychains are considered equal if data is equal
77	return (mCertificate < other.mCertificate);
78}
79
80bool
81Identity::operator == (const Identity &other) const
82{
83	// Certificates in different keychains are considered equal if data is equal;
84	// however, if their keys are in different keychains, the identities should
85	// not be considered equal (according to mb)
86	return (mCertificate == other.mCertificate && mPrivateKey == other.mPrivateKey);
87}
88
89bool Identity::equal(SecCFObject &other)
90{
91	CFHashCode this_hash = hash();
92	CFHashCode other_hash = other.hash();
93	return (this_hash == other_hash);
94}
95
96CFHashCode Identity::hash()
97{
98	CFHashCode result = SecCFObject::hash();
99
100
101    struct keyAndCertHash
102    {
103        CFHashCode keyHash;
104        CFHashCode certHash;
105    };
106
107    struct keyAndCertHash hashes;
108    memset(&hashes, 0, sizeof(struct keyAndCertHash));
109
110	KeyItem* pKeyItem = mPrivateKey.get();
111	if (NULL != pKeyItem)
112	{
113		hashes.keyHash = pKeyItem->hash();
114	}
115
116	Certificate* pCert = mCertificate.get();
117	if (NULL != pCert)
118	{
119		hashes.certHash = pCert->hash();
120	}
121
122	if (hashes.keyHash != 0 || hashes.certHash != 0)
123	{
124
125		CFDataRef temp_data = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)&hashes, sizeof(struct keyAndCertHash), kCFAllocatorNull);
126		if (NULL != temp_data)
127		{
128			result = CFHash(temp_data);
129			CFRelease(temp_data);
130		}
131	}
132
133	return result;
134}
135
136