]> git.saurik.com Git - apple/security.git/blob - Keychain/TrustItem.cpp
Security-163.tar.gz
[apple/security.git] / Keychain / TrustItem.cpp
1 /*
2 * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18 //
19 // TrustStore.h - Abstract interface to permanent user trust assignments
20 //
21 #include <Security/TrustItem.h>
22 #include <Security/Schema.h>
23 #include <Security/SecCFTypes.h>
24
25 #include <SecurityNssAsn1/secasn1.h>
26 #include <SecurityNssAsn1/SecNssCoder.h>
27 #include <Security/oidscert.h>
28
29
30 namespace Security {
31 namespace KeychainCore {
32
33
34 //
35 // Construct a UserTrustItem from attributes and initial content
36 //
37 UserTrustItem::UserTrustItem(Certificate *cert, Policy *policy, const TrustData &trustData) :
38 ItemImpl(CSSM_DL_DB_RECORD_USER_TRUST,
39 reinterpret_cast<SecKeychainAttributeList *>(NULL),
40 UInt32(sizeof(trustData)),
41 reinterpret_cast<const void *>(&trustData)),
42 mCertificate(cert), mPolicy(policy)
43 {
44 secdebug("usertrust", "create %p (%p,%p) = %d", this, cert, policy, trustData.trust);
45 }
46
47
48 //
49 // Destroy it
50 //
51 UserTrustItem::~UserTrustItem() throw()
52 {
53 secdebug("usertrust", "destroy %p", this);
54 }
55
56
57 //
58 // Retrieve the trust value from a UserTrustItem
59 //
60 UserTrustItem::TrustData UserTrustItem::trust()
61 {
62 CssmDataContainer data;
63 getData(data);
64 if (data.length() != sizeof(TrustData))
65 MacOSError::throwMe(errSecInvalidTrustSetting);
66 return *data.interpretedAs<TrustData>();
67 }
68
69
70 //
71 // Add item to keychain
72 //
73 PrimaryKey UserTrustItem::add(Keychain &keychain)
74 {
75 // If we already have a Keychain we can't be added.
76 if (mKeychain)
77 MacOSError::throwMe(errSecDuplicateItem);
78
79 populateAttributes();
80
81 CSSM_DB_RECORDTYPE recordType = mDbAttributes->recordType();
82
83 Db db(keychain->database());
84 // add the item to the (regular) db
85 try
86 {
87 mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get());
88 secdebug("usertrust", "%p inserted", this);
89 }
90 catch (const CssmError &e)
91 {
92 if (e.cssmError() != CSSMERR_DL_INVALID_RECORDTYPE)
93 throw;
94
95 // Create the cert relation and try again.
96 secdebug("usertrust", "adding schema relation for user trusts");
97 db->createRelation(CSSM_DL_DB_RECORD_USER_TRUST, "CSSM_DL_DB_RECORD_USER_TRUST",
98 Schema::UserTrustSchemaAttributeCount,
99 Schema::UserTrustSchemaAttributeList,
100 Schema::UserTrustSchemaIndexCount,
101 Schema::UserTrustSchemaIndexList);
102 keychain->resetSchema();
103
104 mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get());
105 secdebug("usertrust", "%p inserted now", this);
106 }
107
108 mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId);
109 mKeychain = keychain;
110 return mPrimaryKey;
111 }
112
113
114 void UserTrustItem::populateAttributes()
115 {
116 CssmAutoData encodedIndex(CssmAllocator::standard());
117 makeCertIndex(mCertificate, encodedIndex);
118 const CssmOid &policyOid = mPolicy->oid();
119
120 mDbAttributes->add(Schema::attributeInfo(kSecTrustCertAttr), encodedIndex.get());
121 mDbAttributes->add(Schema::attributeInfo(kSecTrustPolicyAttr), policyOid);
122 }
123
124
125 //
126 // An ad-hoc hold-and-destroy accessor for a single-valued certificate field
127 //
128 class CertField {
129 public:
130 CertField(Certificate *cert, const CSSM_OID &inField)
131 : certificate(cert), field(inField)
132 { mData = certificate->copyFirstFieldValue(field); }
133
134 ~CertField() { certificate->releaseFieldValue(field, mData); }
135
136 Certificate * const certificate;
137 const CSSM_OID &field;
138
139 operator bool () const { return mData && mData->Data; }
140 CssmData &data() const { return CssmData::overlay(*mData); }
141
142 private:
143 CSSM_DATA_PTR mData;
144 };
145
146
147 //
148 // Construct a trust item index.
149 // This is an ASN.1 sequence of issuer and serial number.
150 //
151 struct IssuerAndSN {
152 CSSM_DATA issuer;
153 CSSM_DATA serial;
154 };
155
156 static const SEC_ASN1Template issuerAndSNTemplate[] = {
157 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(IssuerAndSN) },
158 { SEC_ASN1_OCTET_STRING, offsetof(IssuerAndSN, issuer) },
159 { SEC_ASN1_OCTET_STRING, offsetof(IssuerAndSN, serial) },
160 { 0 }
161 };
162
163 void UserTrustItem::makeCertIndex(Certificate *cert, CssmOwnedData &encodedIndex)
164 {
165 CertField issuer(cert, CSSMOID_X509V1IssuerName);
166 CertField serial(cert, CSSMOID_X509V1SerialNumber);
167 IssuerAndSN index;
168 index.issuer = issuer.data();
169 index.serial = serial.data();
170 if (SecNssEncodeItemOdata(&index, issuerAndSNTemplate, encodedIndex))
171 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
172 }
173
174
175 } // end namespace KeychainCore
176 } // end namespace Security