2 * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 // TrustStore.h - Abstract interface to permanent user trust assignments
27 #include <security_keychain/TrustItem.h>
28 #include <security_cdsa_utilities/Schema.h>
29 #include <security_keychain/SecCFTypes.h>
31 #include <security_asn1/secasn1.h>
32 #include <security_asn1/SecNssCoder.h>
33 #include <Security/oidscert.h>
37 namespace KeychainCore
{
41 // Construct a UserTrustItem from attributes and initial content
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
)
50 secinfo("usertrust", "%p create(%p,%p) = %d",
51 this, cert
, policy
, SecTrustUserSetting(trustData
.trust
));
58 UserTrustItem::~UserTrustItem()
60 secinfo("usertrust", "%p destroyed", this);
65 // Retrieve the trust value from a UserTrustItem
67 UserTrustItem::TrustData
UserTrustItem::trust()
69 StLock
<Mutex
>_(mMutex
);
70 CssmDataContainer data
;
72 if (data
.length() != sizeof(TrustData
))
73 MacOSError::throwMe(errSecInvalidTrustSetting
);
74 return *data
.interpretedAs
<TrustData
>();
79 // Add item to keychain
81 PrimaryKey
UserTrustItem::add(Keychain
&keychain
)
83 StLock
<Mutex
>_(mMutex
);
84 // If we already have a Keychain we can't be added.
86 MacOSError::throwMe(errSecDuplicateItem
);
90 CSSM_DB_RECORDTYPE recordType
= mDbAttributes
->recordType();
92 Db
db(keychain
->database());
93 // add the item to the (regular) db
96 mUniqueId
= db
->insert(recordType
, mDbAttributes
.get(), mData
.get());
97 secinfo("usertrust", "%p inserted", this);
99 catch (const CssmError
&e
)
101 if (e
.osStatus() != CSSMERR_DL_INVALID_RECORDTYPE
)
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
);
119 mUniqueId
= db
->insert(recordType
, mDbAttributes
.get(), mData
.get());
120 secinfo("usertrust", "%p inserted now", this);
123 mPrimaryKey
= keychain
->makePrimaryKey(recordType
, mUniqueId
);
124 mKeychain
= keychain
;
129 void UserTrustItem::populateAttributes()
131 StLock
<Mutex
>_(mMutex
);
132 CssmAutoData
encodedIndex(Allocator::standard());
133 makeCertIndex(mCertificate
, encodedIndex
);
134 const CssmOid
&policyOid
= mPolicy
->oid();
136 mDbAttributes
->add(Schema::attributeInfo(kSecTrustCertAttr
), encodedIndex
.get());
137 mDbAttributes
->add(Schema::attributeInfo(kSecTrustPolicyAttr
), policyOid
);
142 // An ad-hoc hold-and-destroy accessor for a single-valued certificate field
146 CertField(Certificate
*cert
, const CSSM_OID
&inField
)
147 : certificate(cert
), field(inField
)
148 { mData
= certificate
->copyFirstFieldValue(field
); }
150 ~CertField() { certificate
->releaseFieldValue(field
, mData
); }
152 Certificate
* const certificate
;
153 const CSSM_OID
&field
;
155 operator bool () const { return mData
&& mData
->Data
; }
156 CssmData
&data() const { return CssmData::overlay(*mData
); }
164 // Construct a trust item index.
165 // This is an ASN.1 sequence of issuer and serial number.
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
) },
179 void UserTrustItem::makeCertIndex(Certificate
*cert
, CssmOwnedData
&encodedIndex
)
181 CertField
issuer(cert
, CSSMOID_X509V1IssuerName
);
182 CertField
serial(cert
, CSSMOID_X509V1SerialNumber
);
184 index
.issuer
= issuer
.data();
185 index
.serial
= serial
.data();
186 if (SecNssEncodeItemOdata(&index
, issuerAndSNTemplate
, encodedIndex
))
187 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
191 } // end namespace KeychainCore
192 } // end namespace Security