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