]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/TrustItem.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / TrustItem.cpp
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 // TrustStore.h - Abstract interface to permanent user trust assignments
26 //
27 #include <security_keychain/TrustItem.h>
28 #include <security_cdsa_utilities/Schema.h>
29 #include <security_keychain/SecCFTypes.h>
30
31 #include <security_asn1/secasn1.h>
32 #include <security_asn1/SecNssCoder.h>
33 #include <Security/oidscert.h>
34
35
36 namespace Security {
37 namespace KeychainCore {
38
39
40 //
41 // Construct a UserTrustItem from attributes and initial content
42 //
43 UserTrustItem::UserTrustItem(Certificate *cert, Policy *policy, const TrustData &trustData) :
44 ItemImpl((SecItemClass)CSSM_DL_DB_RECORD_USER_TRUST,
45 reinterpret_cast<SecKeychainAttributeList *>(NULL),
46 UInt32(sizeof(trustData)),
47 reinterpret_cast<const void *>(&trustData)),
48 mCertificate(cert), mPolicy(policy)
49 {
50 secinfo("usertrust", "%p create(%p,%p) = %d",
51 this, cert, policy, SecTrustUserSetting(trustData.trust));
52 }
53
54
55 //
56 // Destroy it
57 //
58 UserTrustItem::~UserTrustItem()
59 {
60 secinfo("usertrust", "%p destroyed", this);
61 }
62
63
64 //
65 // Retrieve the trust value from a UserTrustItem
66 //
67 UserTrustItem::TrustData UserTrustItem::trust()
68 {
69 StLock<Mutex>_(mMutex);
70 CssmDataContainer data;
71 getData(data);
72 if (data.length() != sizeof(TrustData))
73 MacOSError::throwMe(errSecInvalidTrustSetting);
74 return *data.interpretedAs<TrustData>();
75 }
76
77
78 //
79 // Add item to keychain
80 //
81 PrimaryKey UserTrustItem::add(Keychain &keychain)
82 {
83 StLock<Mutex>_(mMutex);
84 // If we already have a Keychain we can't be added.
85 if (mKeychain)
86 MacOSError::throwMe(errSecDuplicateItem);
87
88 populateAttributes();
89
90 CSSM_DB_RECORDTYPE recordType = mDbAttributes->recordType();
91
92 Db db(keychain->database());
93 // add the item to the (regular) db
94 try
95 {
96 mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get());
97 secinfo("usertrust", "%p inserted", this);
98 }
99 catch (const CssmError &e)
100 {
101 if (e.osStatus() != CSSMERR_DL_INVALID_RECORDTYPE)
102 throw;
103
104 // Create the trust relation and try again.
105 secinfo("usertrust", "adding schema relation for user trusts");
106 db->createRelation(CSSM_DL_DB_RECORD_USER_TRUST, "CSSM_DL_DB_RECORD_USER_TRUST",
107 Schema::UserTrustSchemaAttributeCount,
108 Schema::UserTrustSchemaAttributeList,
109 Schema::UserTrustSchemaIndexCount,
110 Schema::UserTrustSchemaIndexList);
111 keychain->keychainSchema()->didCreateRelation(
112 CSSM_DL_DB_RECORD_USER_TRUST,
113 "CSSM_DL_DB_RECORD_USER_TRUST",
114 Schema::UserTrustSchemaAttributeCount,
115 Schema::UserTrustSchemaAttributeList,
116 Schema::UserTrustSchemaIndexCount,
117 Schema::UserTrustSchemaIndexList);
118
119 mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get());
120 secinfo("usertrust", "%p inserted now", this);
121 }
122
123 mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId);
124 mKeychain = keychain;
125 return mPrimaryKey;
126 }
127
128
129 void UserTrustItem::populateAttributes()
130 {
131 StLock<Mutex>_(mMutex);
132 CssmAutoData encodedIndex(Allocator::standard());
133 makeCertIndex(mCertificate, encodedIndex);
134 const CssmOid &policyOid = mPolicy->oid();
135
136 mDbAttributes->add(Schema::attributeInfo(kSecTrustCertAttr), encodedIndex.get());
137 mDbAttributes->add(Schema::attributeInfo(kSecTrustPolicyAttr), policyOid);
138 }
139
140
141 //
142 // An ad-hoc hold-and-destroy accessor for a single-valued certificate field
143 //
144 class CertField {
145 public:
146 CertField(Certificate *cert, const CSSM_OID &inField)
147 : certificate(cert), field(inField)
148 { mData = certificate->copyFirstFieldValue(field); }
149
150 ~CertField() { certificate->releaseFieldValue(field, mData); }
151
152 Certificate * const certificate;
153 const CSSM_OID &field;
154
155 operator bool () const { return mData && mData->Data; }
156 CssmData &data() const { return CssmData::overlay(*mData); }
157
158 private:
159 CSSM_DATA_PTR mData;
160 };
161
162
163 //
164 // Construct a trust item index.
165 // This is an ASN.1 sequence of issuer and serial number.
166 //
167 struct IssuerAndSN {
168 CSSM_DATA issuer;
169 CSSM_DATA serial;
170 };
171
172 static const SecAsn1Template issuerAndSNTemplate[] = {
173 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(IssuerAndSN) },
174 { SEC_ASN1_OCTET_STRING, offsetof(IssuerAndSN, issuer) },
175 { SEC_ASN1_OCTET_STRING, offsetof(IssuerAndSN, serial) },
176 { 0 }
177 };
178
179 void UserTrustItem::makeCertIndex(Certificate *cert, CssmOwnedData &encodedIndex)
180 {
181 CertField issuer(cert, CSSMOID_X509V1IssuerName);
182 CertField serial(cert, CSSMOID_X509V1SerialNumber);
183 IssuerAndSN index;
184 index.issuer = issuer.data();
185 index.serial = serial.data();
186 if (SecNssEncodeItemOdata(&index, issuerAndSNTemplate, encodedIndex))
187 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
188 }
189
190
191 } // end namespace KeychainCore
192 } // end namespace Security