]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_keychain/lib/TrustItem.cpp
Security-58286.51.6.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / TrustItem.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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
36namespace Security {
37namespace KeychainCore {
38
39
40//
41// Construct a UserTrustItem from attributes and initial content
42//
43UserTrustItem::UserTrustItem(Certificate *cert, Policy *policy, const TrustData &trustData) :
6b200bc3 44 ItemImpl((SecItemClass)CSSM_DL_DB_RECORD_USER_TRUST,
b1ab9ed8
A
45 reinterpret_cast<SecKeychainAttributeList *>(NULL),
46 UInt32(sizeof(trustData)),
47 reinterpret_cast<const void *>(&trustData)),
48 mCertificate(cert), mPolicy(policy)
49{
fa7225c8 50 secinfo("usertrust", "%p create(%p,%p) = %d",
b1ab9ed8
A
51 this, cert, policy, SecTrustUserSetting(trustData.trust));
52}
53
54
55//
56// Destroy it
57//
58UserTrustItem::~UserTrustItem()
59{
fa7225c8 60 secinfo("usertrust", "%p destroyed", this);
b1ab9ed8
A
61}
62
63
64//
65// Retrieve the trust value from a UserTrustItem
66//
67UserTrustItem::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//
81PrimaryKey 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());
fa7225c8 97 secinfo("usertrust", "%p inserted", this);
b1ab9ed8
A
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.
fa7225c8 105 secinfo("usertrust", "adding schema relation for user trusts");
b1ab9ed8
A
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());
fa7225c8 120 secinfo("usertrust", "%p inserted now", this);
b1ab9ed8
A
121 }
122
123 mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId);
124 mKeychain = keychain;
125 return mPrimaryKey;
126}
127
128
129void 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//
144class CertField {
145public:
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
158private:
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//
167struct IssuerAndSN {
168 CSSM_DATA issuer;
169 CSSM_DATA serial;
170};
171
172static 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
179void 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