2 * Copyright (c) 2002-2004 Apple Computer, 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@
27 #include <security_keychain/KeyItem.h>
28 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
29 #include <Security/cssmtype.h>
30 #include <security_keychain/Access.h>
31 #include <security_keychain/Keychains.h>
32 #include <security_keychain/KeyItem.h>
33 #include <security_cdsa_client/wrapkey.h>
34 #include <security_cdsa_client/genkey.h>
35 #include <security_cdsa_client/signclient.h>
36 #include <security_cdsa_client/cryptoclient.h>
38 #include <security_keychain/Globals.h>
39 #include "KCEventNotifier.h"
41 // @@@ This needs to be shared.
42 static CSSM_DB_NAME_ATTR(kInfoKeyPrintName
, kSecKeyPrintName
, (char*) "PrintName", 0, NULL
, BLOB
);
43 static CSSM_DB_NAME_ATTR(kInfoKeyLabel
, kSecKeyLabel
, (char*) "Label", 0, NULL
, BLOB
);
44 static CSSM_DB_NAME_ATTR(kInfoKeyApplicationTag
, kSecKeyApplicationTag
, (char*) "ApplicationTag", 0, NULL
, BLOB
);
46 using namespace KeychainCore
;
47 using namespace CssmClient
;
49 KeyItem::KeyItem(const Keychain
&keychain
, const PrimaryKey
&primaryKey
, const CssmClient::DbUniqueRecord
&uniqueId
) :
50 ItemImpl(keychain
, primaryKey
, uniqueId
),
53 mPubKeyHash(Allocator::standard())
57 KeyItem::KeyItem(const Keychain
&keychain
, const PrimaryKey
&primaryKey
) :
58 ItemImpl(keychain
, primaryKey
),
61 mPubKeyHash(Allocator::standard())
65 KeyItem
* KeyItem::make(const Keychain
&keychain
, const PrimaryKey
&primaryKey
, const CssmClient::DbUniqueRecord
&uniqueId
)
67 KeyItem
* k
= new KeyItem(keychain
, primaryKey
, uniqueId
);
68 keychain
->addItem(primaryKey
, k
);
74 KeyItem
* KeyItem::make(const Keychain
&keychain
, const PrimaryKey
&primaryKey
)
76 KeyItem
* k
= new KeyItem(keychain
, primaryKey
);
77 keychain
->addItem(primaryKey
, k
);
83 KeyItem::KeyItem(KeyItem
&keyItem
) :
87 mPubKeyHash(Allocator::standard())
89 // @@@ this doesn't work for keys that are not in a keychain.
92 KeyItem::KeyItem(const CssmClient::Key
&key
) :
93 ItemImpl(key
->keyClass() + CSSM_DL_DB_RECORD_PUBLIC_KEY
, (OSType
)0, (UInt32
)0, (const void*)NULL
),
96 mPubKeyHash(Allocator::standard())
98 if (key
->keyClass() > CSSM_KEYCLASS_SESSION_KEY
)
99 MacOSError::throwMe(paramErr
);
113 KeyItem::copyTo(const Keychain
&keychain
, Access
*newAccess
)
115 if (!(keychain
->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP
))
116 MacOSError::throwMe(errSecInvalidKeychain
);
118 /* Get the destination keychain's db. */
119 SSDbImpl
* dbImpl
= dynamic_cast<SSDbImpl
*>(&(*keychain
->database()));
122 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
127 /* Make sure mKey is valid. */
130 // Generate a random label to use initially
131 CssmClient::CSP
appleCsp(gGuidAppleCSP
);
132 CssmClient::Random
random(appleCsp
, CSSM_ALGID_APPLE_YARROW
);
133 uint8 labelBytes
[20];
134 CssmData
label(labelBytes
, sizeof(labelBytes
));
135 random
.generate(label
, label
.Length
);
137 /* Set up the ACL for the new key. */
138 SecPointer
<Access
> access
;
142 access
= new Access(*mKey
);
144 /* Generate a random 3DES wrapping Key. */
145 CssmClient::GenerateKey
genKey(csp(), CSSM_ALGID_3DES_3KEY
, 192);
146 CssmClient::Key
wrappingKey(genKey(KeySpec(CSSM_KEYUSE_WRAP
| CSSM_KEYUSE_UNWRAP
,
147 CSSM_KEYATTR_EXTRACTABLE
/* | CSSM_KEYATTR_RETURN_DATA */)));
149 /* make a random IV */
151 CssmData
iv(ivBytes
, sizeof(ivBytes
));
152 random
.generate(iv
, iv
.length());
154 /* Extract the key by wrapping it with the wrapping key. */
155 CssmClient::WrapKey
wrap(csp(), CSSM_ALGID_3DES_3KEY_EDE
);
156 wrap
.key(wrappingKey
);
157 wrap
.cred(getCredentials(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
, kSecCredentialTypeDefault
));
158 wrap
.mode(CSSM_ALGMODE_ECBPad
);
159 wrap
.padding(CSSM_PADDING_PKCS7
);
161 CssmClient::Key
wrappedKey(wrap(mKey
));
163 /* Unwrap the new key into the new Keychain. */
164 CssmClient::UnwrapKey
unwrap(keychain
->csp(), CSSM_ALGID_3DES_3KEY_EDE
);
165 unwrap
.key(wrappingKey
);
166 unwrap
.mode(CSSM_ALGMODE_ECBPad
);
167 unwrap
.padding(CSSM_PADDING_PKCS7
);
168 unwrap
.initVector(iv
);
170 /* Setup the dldbHandle in the context. */
171 unwrap
.add(CSSM_ATTRIBUTE_DL_DB_HANDLE
, ssDb
->handle());
173 /* Set up an initial aclEntry so we can change it after the unwrap. */
174 Access::Maker
maker(Allocator::standard(), Access::Maker::kAnyMakerType
);
175 ResourceControlContext rcc
;
176 maker
.initialOwner(rcc
, NULL
);
177 unwrap
.owner(rcc
.input());
179 /* Unwrap the key. */
180 uint32 usage
= mKey
->usage();
181 /* Work around csp brokeness where it sets all usage bits in the Keyheader when CSSM_KEYUSE_ANY is set. */
182 if (usage
& CSSM_KEYUSE_ANY
)
183 usage
= CSSM_KEYUSE_ANY
;
185 CssmClient::Key
unwrappedKey(unwrap(wrappedKey
, KeySpec(usage
,
186 (mKey
->attributes() | CSSM_KEYATTR_PERMANENT
) & ~(CSSM_KEYATTR_ALWAYS_SENSITIVE
| CSSM_KEYATTR_NEVER_EXTRACTABLE
),
189 /* Look up unwrapped key in the DLDB. */
190 DbUniqueRecord uniqueId
;
191 SSDbCursor
dbCursor(ssDb
, 1);
192 dbCursor
->recordType(recordType());
193 dbCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, label
);
194 CssmClient::Key copiedKey
;
195 if (!dbCursor
->nextKey(NULL
, copiedKey
, uniqueId
))
196 MacOSError::throwMe(errSecItemNotFound
);
198 /* Copy the Label, PrintName and ApplicationTag attributes from the old key to the new one. */
200 DbAttributes
oldDbAttributes(mUniqueId
->database(), 3);
201 oldDbAttributes
.add(kInfoKeyLabel
);
202 oldDbAttributes
.add(kInfoKeyPrintName
);
203 oldDbAttributes
.add(kInfoKeyApplicationTag
);
204 mUniqueId
->get(&oldDbAttributes
, NULL
);
207 uniqueId
->modify(recordType(), &oldDbAttributes
, NULL
, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
211 // clean up after trying to insert a duplicate key
212 uniqueId
->deleteRecord ();
216 /* Set the acl and owner on the unwrapped key. */
217 access
->setAccess(*unwrappedKey
, maker
);
219 /* Return a keychain item which represents the new key. */
220 Item
item(keychain
->item(recordType(), uniqueId
));
222 KCEventNotifier::PostKeychainEvent(kSecAddEvent
, keychain
, item
);
228 KeyItem::importTo(const Keychain
&keychain
, Access
*newAccess
, SecKeychainAttributeList
*attrList
)
230 if (!(keychain
->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP
))
231 MacOSError::throwMe(errSecInvalidKeychain
);
233 /* Get the destination keychain's db. */
234 SSDbImpl
* dbImpl
= dynamic_cast<SSDbImpl
*>(&(*keychain
->database()));
236 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
240 /* Make sure mKey is valid. */
241 /* We can't call key() here, since we won't have a unique record id yet */
243 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
245 // Generate a random label to use initially
246 CssmClient::CSP
appleCsp(gGuidAppleCSP
);
247 CssmClient::Random
random(appleCsp
, CSSM_ALGID_APPLE_YARROW
);
248 uint8 labelBytes
[20];
249 CssmData
label(labelBytes
, sizeof(labelBytes
));
250 random
.generate(label
, label
.Length
);
252 /* Set up the ACL for the new key. */
253 SecPointer
<Access
> access
;
257 access
= new Access(*mKey
);
259 /* Generate a random 3DES wrapping Key. */
260 CssmClient::GenerateKey
genKey(csp(), CSSM_ALGID_3DES_3KEY
, 192);
261 CssmClient::Key
wrappingKey(genKey(KeySpec(CSSM_KEYUSE_WRAP
| CSSM_KEYUSE_UNWRAP
,
262 CSSM_KEYATTR_EXTRACTABLE
/* | CSSM_KEYATTR_RETURN_DATA */)));
264 /* make a random IV */
266 CssmData
iv(ivBytes
, sizeof(ivBytes
));
267 random
.generate(iv
, iv
.length());
269 /* Extract the key by wrapping it with the wrapping key. */
270 CssmClient::WrapKey
wrap(csp(), CSSM_ALGID_3DES_3KEY_EDE
);
271 wrap
.key(wrappingKey
);
272 wrap
.cred(getCredentials(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
, kSecCredentialTypeDefault
));
273 wrap
.mode(CSSM_ALGMODE_ECBPad
);
274 wrap
.padding(CSSM_PADDING_PKCS7
);
276 CssmClient::Key
wrappedKey(wrap(mKey
));
278 /* Unwrap the new key into the new Keychain. */
279 CssmClient::UnwrapKey
unwrap(keychain
->csp(), CSSM_ALGID_3DES_3KEY_EDE
);
280 unwrap
.key(wrappingKey
);
281 unwrap
.mode(CSSM_ALGMODE_ECBPad
);
282 unwrap
.padding(CSSM_PADDING_PKCS7
);
283 unwrap
.initVector(iv
);
285 /* Setup the dldbHandle in the context. */
286 unwrap
.add(CSSM_ATTRIBUTE_DL_DB_HANDLE
, ssDb
->handle());
288 /* Set up an initial aclEntry so we can change it after the unwrap. */
289 Access::Maker
maker(Allocator::standard(), Access::Maker::kAnyMakerType
);
290 ResourceControlContext rcc
;
291 maker
.initialOwner(rcc
, NULL
);
292 unwrap
.owner(rcc
.input());
294 /* Unwrap the key. */
295 uint32 usage
= mKey
->usage();
296 /* Work around csp brokeness where it sets all usage bits in the Keyheader when CSSM_KEYUSE_ANY is set. */
297 if (usage
& CSSM_KEYUSE_ANY
)
298 usage
= CSSM_KEYUSE_ANY
;
300 CssmClient::Key
unwrappedKey(unwrap(wrappedKey
, KeySpec(usage
,
301 (mKey
->attributes() | CSSM_KEYATTR_PERMANENT
) & ~(CSSM_KEYATTR_ALWAYS_SENSITIVE
| CSSM_KEYATTR_NEVER_EXTRACTABLE
),
304 /* Look up unwrapped key in the DLDB. */
305 DbUniqueRecord uniqueId
;
306 SSDbCursor
dbCursor(ssDb
, 1);
307 dbCursor
->recordType(recordType());
308 dbCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, label
);
309 CssmClient::Key copiedKey
;
310 if (!dbCursor
->nextKey(NULL
, copiedKey
, uniqueId
))
311 MacOSError::throwMe(errSecItemNotFound
);
313 // Set the initial label, application label, and application tag (if provided)
315 DbAttributes newDbAttributes
;
316 SSDbCursor
otherDbCursor(ssDb
, 1);
317 otherDbCursor
->recordType(recordType());
318 bool checkForDuplicates
= false;
320 for (UInt32 index
=0; index
< attrList
->count
; index
++) {
321 SecKeychainAttribute attr
= attrList
->attr
[index
];
322 CssmData
attrData(attr
.data
, attr
.length
);
323 if (attr
.tag
== kSecKeyPrintName
) {
324 newDbAttributes
.add(kInfoKeyPrintName
, attrData
);
326 if (attr
.tag
== kSecKeyLabel
) {
327 newDbAttributes
.add(kInfoKeyLabel
, attrData
);
328 otherDbCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, attrData
);
329 checkForDuplicates
= true;
331 if (attr
.tag
== kSecKeyApplicationTag
) {
332 newDbAttributes
.add(kInfoKeyApplicationTag
, attrData
);
333 otherDbCursor
->add(CSSM_DB_EQUAL
, kInfoKeyApplicationTag
, attrData
);
334 checkForDuplicates
= true;
338 DbAttributes otherDbAttributes
;
339 DbUniqueRecord otherUniqueId
;
340 CssmClient::Key otherKey
;
343 if (checkForDuplicates
&& otherDbCursor
->nextKey(&otherDbAttributes
, otherKey
, otherUniqueId
))
344 MacOSError::throwMe(errSecDuplicateItem
);
346 uniqueId
->modify(recordType(), &newDbAttributes
, NULL
, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
350 // clean up after trying to insert a duplicate key
351 uniqueId
->deleteRecord ();
356 /* Set the acl and owner on the unwrapped key. */
357 access
->setAccess(*unwrappedKey
, maker
);
359 /* Return a keychain item which represents the new key. */
360 Item
item(keychain
->item(recordType(), uniqueId
));
362 KCEventNotifier::PostKeychainEvent(kSecAddEvent
, keychain
, item
);
373 KeyItem::add(Keychain
&keychain
)
375 MacOSError::throwMe(unimpErr
);
378 CssmClient::SSDbUniqueRecord
379 KeyItem::ssDbUniqueRecord()
381 DbUniqueRecordImpl
*impl
= &*dbUniqueRecord();
382 Security::CssmClient::SSDbUniqueRecordImpl
*simpl
= dynamic_cast<Security::CssmClient::SSDbUniqueRecordImpl
*>(impl
);
385 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
388 return CssmClient::SSDbUniqueRecord(simpl
);
396 CssmClient::SSDbUniqueRecord
uniqueId(ssDbUniqueRecord());
397 CssmDataContainer
dataBlob(uniqueId
->allocator());
398 uniqueId
->get(NULL
, &dataBlob
);
399 mKey
= CssmClient::Key(uniqueId
->database()->csp(), *reinterpret_cast<CssmKey
*>(dataBlob
.Data
));
412 const CSSM_X509_ALGORITHM_IDENTIFIER
&
413 KeyItem::algorithmIdentifier()
417 CSSM_KEY_TYPE algorithm
418 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
)thisData
->Data
;
420 static void printKeyHeader(
421 const CSSM_KEYHEADER
&hdr
)
423 printf(" Algorithm : ");
424 switch(hdr
.AlgorithmId
) {
425 CSSM_X509_ALGORITHM_IDENTIFIER algID
;
427 CSSM_OID
*CL_algToOid(
428 CSSM_ALGORITHMS algId
)
429 typedef struct cssm_x509_algorithm_identifier
{
431 CSSM_DATA parameters
;
432 } CSSM_X509_ALGORITHM_IDENTIFIER
, *CSSM_X509_ALGORITHM_IDENTIFIER_PTR
;
439 * itemID, used to locate Extended Attributes, is the public key hash for keys.
441 const CssmData
&KeyItem::itemID()
443 if(mPubKeyHash
.length() == 0) {
445 * Fetch the attribute from disk.
447 UInt32 tag
= kSecKeyLabel
;
449 SecKeychainAttributeInfo attrInfo
= {1, &tag
, &format
};
450 SecKeychainAttributeList
*attrList
= NULL
;
451 getAttributesAndData(&attrInfo
, NULL
, &attrList
, NULL
, NULL
);
452 if((attrList
== NULL
) || (attrList
->count
!= 1)) {
453 MacOSError::throwMe(errSecNoSuchAttr
);
455 mPubKeyHash
.copy(attrList
->attr
->data
, attrList
->attr
->length
);
456 freeAttributesAndData(attrList
, NULL
);
463 KeyItem::strengthInBits(const CSSM_X509_ALGORITHM_IDENTIFIER
*algid
)
465 // @@@ Make a context with key based on algid and use that to get the effective keysize and not just the logical one.
466 CSSM_KEY_SIZE keySize
= {};
467 CSSM_RETURN rv
= CSSM_QueryKeySizeInBits (csp()->handle(),
474 return keySize
.LogicalKeySizeInBits
;
477 const AccessCredentials
*
478 KeyItem::getCredentials(
479 CSSM_ACL_AUTHORIZATION_TAG operation
,
480 SecCredentialType credentialType
)
482 // @@@ Fix this to actually examine the ACL for this key and consider operation and do the right thing.
483 //AutoAclEntryInfoList aclInfos;
484 //key()->getAcl(aclInfos);
486 bool smartcard
= keychain() != NULL
? (keychain()->database()->dl()->guid() == gGuidAppleSdCSPDL
) : false;
489 switch (credentialType
)
491 case kSecCredentialTypeDefault
:
492 return smartcard
?globals().smartcardItemCredentials():globals().itemCredentials();
493 case kSecCredentialTypeWithUI
:
494 return smartcard
?globals().smartcardItemCredentials():factory
.promptCred();
495 case kSecCredentialTypeNoUI
:
496 return factory
.nullCred();
498 MacOSError::throwMe(paramErr
);
503 KeyItem::operator == (KeyItem
&other
)
508 return this == &other
;
511 // If keychains are different, then keys are different
512 Keychain otherKeychain
= other
.keychain();
513 return (mKeychain
&& otherKeychain
&& (*mKeychain
== *otherKeychain
));
519 CSSM_ALGORITHMS algorithm
,
520 uint32 keySizeInBits
,
521 CSSM_CC_HANDLE contextHandle
,
522 CSSM_KEYUSE publicKeyUsage
,
523 uint32 publicKeyAttr
,
524 CSSM_KEYUSE privateKeyUsage
,
525 uint32 privateKeyAttr
,
526 SecPointer
<Access
> initialAccess
,
527 SecPointer
<KeyItem
> &outPublicKey
,
528 SecPointer
<KeyItem
> &outPrivateKey
)
530 bool freeKeys
= false;
531 bool deleteContext
= false;
533 if (!(keychain
->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP
))
534 MacOSError::throwMe(errSecInvalidKeychain
);
536 SSDbImpl
* impl
= dynamic_cast<SSDbImpl
*>(&(*keychain
->database()));
539 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
543 CssmClient::CSP
csp(keychain
->csp());
544 CssmClient::CSP
appleCsp(gGuidAppleCSP
);
546 // Generate a random label to use initially
547 CssmClient::Random
random(appleCsp
, CSSM_ALGID_APPLE_YARROW
);
548 uint8 labelBytes
[20];
549 CssmData
label(labelBytes
, sizeof(labelBytes
));
550 random
.generate(label
, label
.Length
);
552 // Create a Access::Maker for the initial owner of the private key.
553 ResourceControlContext rcc
;
554 memset(&rcc
, 0, sizeof(rcc
));
556 // @@@ Potentially provide a credential argument which allows us to generate keys in the csp. Currently the CSP let's anyone do this, but we might restrict this in the future, f.e. a smartcard could require out of band pin entry before a key can be generated.
557 maker
.initialOwner(rcc
);
558 // Create the cred we need to manipulate the keys until we actually set a new access control for them.
559 const AccessCredentials
*cred
= maker
.cred();
561 CSSM_KEY publicCssmKey
, privateCssmKey
;
562 memset(&publicCssmKey
, 0, sizeof(publicCssmKey
));
563 memset(&privateCssmKey
, 0, sizeof(privateCssmKey
));
565 CSSM_CC_HANDLE ccHandle
= 0;
567 Item publicKeyItem
, privateKeyItem
;
572 ccHandle
= contextHandle
;
575 status
= CSSM_CSP_CreateKeyGenContext(csp
->handle(), algorithm
, keySizeInBits
, NULL
, NULL
, NULL
, NULL
, NULL
, &ccHandle
);
577 CssmError::throwMe(status
);
578 deleteContext
= true;
581 CSSM_DL_DB_HANDLE dldbHandle
= ssDb
->handle();
582 CSSM_DL_DB_HANDLE_PTR dldbHandlePtr
= &dldbHandle
;
583 CSSM_CONTEXT_ATTRIBUTE contextAttributes
= { CSSM_ATTRIBUTE_DL_DB_HANDLE
, sizeof(dldbHandle
), { (char *)dldbHandlePtr
} };
584 status
= CSSM_UpdateContextAttributes(ccHandle
, 1, &contextAttributes
);
586 CssmError::throwMe(status
);
588 // Generate the keypair
589 status
= CSSM_GenerateKeyPair(ccHandle
, publicKeyUsage
, publicKeyAttr
, &label
, &publicCssmKey
, privateKeyUsage
, privateKeyAttr
, &label
, &rcc
, &privateCssmKey
);
591 CssmError::throwMe(status
);
594 // Find the keys we just generated in the DL to get SecKeyRef's to them
595 // so we can change the label to be the hash of the public key, and
596 // fix up other attributes.
598 // Look up public key in the DLDB.
599 DbAttributes pubDbAttributes
;
600 DbUniqueRecord pubUniqueId
;
601 SSDbCursor
dbPubCursor(ssDb
, 1);
602 dbPubCursor
->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY
);
603 dbPubCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, label
);
604 CssmClient::Key publicKey
;
605 if (!dbPubCursor
->nextKey(&pubDbAttributes
, publicKey
, pubUniqueId
))
606 MacOSError::throwMe(errSecItemNotFound
);
608 // Look up private key in the DLDB.
609 DbAttributes privDbAttributes
;
610 DbUniqueRecord privUniqueId
;
611 SSDbCursor
dbPrivCursor(ssDb
, 1);
612 dbPrivCursor
->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY
);
613 dbPrivCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, label
);
614 CssmClient::Key privateKey
;
615 if (!dbPrivCursor
->nextKey(&privDbAttributes
, privateKey
, privUniqueId
))
616 MacOSError::throwMe(errSecItemNotFound
);
618 // Convert reference public key to a raw key so we can use it
620 CssmClient::WrapKey
wrap(csp
, CSSM_ALGID_NONE
);
622 CssmClient::Key rawPubKey
= wrap(publicKey
);
624 // Calculate the hash of the public key using the appleCSP.
625 CssmClient::PassThrough
passThrough(appleCsp
);
629 /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the
630 * associated key blob.
631 * Key is specified in CSSM_CSP_CreatePassThroughContext.
632 * Hash is allocated bythe CSP, in the App's memory, and returned
634 passThrough
.key(rawPubKey
);
635 passThrough(CSSM_APPLECSP_KEYDIGEST
, NULL
, &outData
);
636 cssmData
= reinterpret_cast<CssmData
*>(outData
);
637 CssmData
&pubKeyHash
= *cssmData
;
639 auto_ptr
<string
>privDescription
;
640 auto_ptr
<string
>pubDescription
;
642 privDescription
.reset(new string(initialAccess
->promptDescription()));
643 pubDescription
.reset(new string(initialAccess
->promptDescription()));
646 /* this path taken if no promptDescription available, e.g., for complex ACLs */
647 privDescription
.reset(new string("Private key"));
648 pubDescription
.reset(new string("Public key"));
651 // Set the label of the public key to the public key hash.
652 // Set the PrintName of the public key to the description in the acl.
653 pubDbAttributes
.add(kInfoKeyLabel
, pubKeyHash
);
654 pubDbAttributes
.add(kInfoKeyPrintName
, *pubDescription
);
655 pubUniqueId
->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY
, &pubDbAttributes
, NULL
, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
657 // Set the label of the private key to the public key hash.
658 // Set the PrintName of the private key to the description in the acl.
659 privDbAttributes
.add(kInfoKeyLabel
, pubKeyHash
);
660 privDbAttributes
.add(kInfoKeyPrintName
, *privDescription
);
661 privUniqueId
->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY
, &privDbAttributes
, NULL
, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
663 // @@@ Not exception safe!
664 csp
.allocator().free(cssmData
->Data
);
665 csp
.allocator().free(cssmData
);
667 // Finally fix the acl and owner of the private key to the specified access control settings.
668 initialAccess
->setAccess(*privateKey
, maker
);
670 if(publicKeyAttr
& CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT
) {
672 * Make the public key acl completely open.
673 * If the key was not encrypted, it already has a wide-open
674 * ACL (though that is a feature of securityd; it's not
675 * CDSA-specified behavior).
677 SecPointer
<Access
> pubKeyAccess(new Access());
678 pubKeyAccess
->setAccess(*publicKey
, maker
);
681 // Create keychain items which will represent the keys.
682 publicKeyItem
= keychain
->item(CSSM_DL_DB_RECORD_PUBLIC_KEY
, pubUniqueId
);
683 privateKeyItem
= keychain
->item(CSSM_DL_DB_RECORD_PRIVATE_KEY
, privUniqueId
);
685 KeyItem
* impl
= dynamic_cast<KeyItem
*>(&(*publicKeyItem
));
688 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
693 impl
= dynamic_cast<KeyItem
*>(&(*privateKeyItem
));
696 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
699 outPrivateKey
= impl
;
705 // Delete the keys if something goes wrong so we don't end up with inaccessible keys in the database.
706 CSSM_FreeKey(csp
->handle(), cred
, &publicCssmKey
, TRUE
);
707 CSSM_FreeKey(csp
->handle(), cred
, &privateCssmKey
, TRUE
);
711 CSSM_DeleteContext(ccHandle
);
718 CSSM_FreeKey(csp
->handle(), NULL
, &publicCssmKey
, FALSE
);
719 CSSM_FreeKey(csp
->handle(), NULL
, &privateCssmKey
, FALSE
);
723 CSSM_DeleteContext(ccHandle
);
725 if (keychain
&& publicKeyItem
&& privateKeyItem
)
727 keychain
->postEvent(kSecAddEvent
, publicKeyItem
);
728 keychain
->postEvent(kSecAddEvent
, privateKeyItem
);
735 const CSSM_KEY
&publicWrappedKey
,
736 const CSSM_KEY
&privateWrappedKey
,
737 SecPointer
<Access
> initialAccess
,
738 SecPointer
<KeyItem
> &outPublicKey
,
739 SecPointer
<KeyItem
> &outPrivateKey
)
741 bool freePublicKey
= false;
742 bool freePrivateKey
= false;
743 bool deleteContext
= false;
745 if (!(keychain
->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP
))
746 MacOSError::throwMe(errSecInvalidKeychain
);
748 SSDbImpl
* impl
= dynamic_cast<SSDbImpl
*>(&(*keychain
->database()));
751 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
755 CssmClient::CSP
csp(keychain
->csp());
756 CssmClient::CSP
appleCsp(gGuidAppleCSP
);
758 // Create a Access::Maker for the initial owner of the private key.
759 ResourceControlContext rcc
;
760 memset(&rcc
, 0, sizeof(rcc
));
761 Access::Maker
maker(Allocator::standard(), Access::Maker::kAnyMakerType
);
762 // @@@ Potentially provide a credential argument which allows us to unwrap keys in the csp.
763 // Currently the CSP lets anyone do this, but we might restrict this in the future, e.g.
764 // a smartcard could require out of band pin entry before a key can be generated.
765 maker
.initialOwner(rcc
);
766 // Create the cred we need to manipulate the keys until we actually set a new access control for them.
767 const AccessCredentials
*cred
= maker
.cred();
769 CSSM_KEY publicCssmKey
, privateCssmKey
;
770 memset(&publicCssmKey
, 0, sizeof(publicCssmKey
));
771 memset(&privateCssmKey
, 0, sizeof(privateCssmKey
));
773 CSSM_CC_HANDLE ccHandle
= 0;
775 Item publicKeyItem
, privateKeyItem
;
780 // Calculate the hash of the public key using the appleCSP.
781 CssmClient::PassThrough
passThrough(appleCsp
);
785 /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the
786 * associated key blob.
787 * Key is specified in CSSM_CSP_CreatePassThroughContext.
788 * Hash is allocated bythe CSP, in the App's memory, and returned
790 passThrough
.key(&publicWrappedKey
);
791 passThrough(CSSM_APPLECSP_KEYDIGEST
, NULL
, &outData
);
792 cssmData
= reinterpret_cast<CssmData
*>(outData
);
793 CssmData
&pubKeyHash
= *cssmData
;
795 status
= CSSM_CSP_CreateSymmetricContext(csp
->handle(), publicWrappedKey
.KeyHeader
.WrapAlgorithmId
, CSSM_ALGMODE_NONE
, NULL
, NULL
, NULL
, CSSM_PADDING_NONE
, NULL
, &ccHandle
);
797 CssmError::throwMe(status
);
798 deleteContext
= true;
800 CSSM_DL_DB_HANDLE dldbHandle
= ssDb
->handle();
801 CSSM_DL_DB_HANDLE_PTR dldbHandlePtr
= &dldbHandle
;
802 CSSM_CONTEXT_ATTRIBUTE contextAttributes
= { CSSM_ATTRIBUTE_DL_DB_HANDLE
, sizeof(dldbHandle
), { (char *)dldbHandlePtr
} };
803 status
= CSSM_UpdateContextAttributes(ccHandle
, 1, &contextAttributes
);
805 CssmError::throwMe(status
);
807 // Unwrap the the keys
808 CSSM_DATA descriptiveData
= {0, NULL
};
810 status
= CSSM_UnwrapKey(
814 publicWrappedKey
.KeyHeader
.KeyUsage
,
815 publicWrappedKey
.KeyHeader
.KeyAttr
| CSSM_KEYATTR_PERMANENT
,
822 CssmError::throwMe(status
);
823 freePublicKey
= true;
825 if (descriptiveData
.Data
!= NULL
)
826 free (descriptiveData
.Data
);
828 status
= CSSM_UnwrapKey(
832 privateWrappedKey
.KeyHeader
.KeyUsage
,
833 privateWrappedKey
.KeyHeader
.KeyAttr
| CSSM_KEYATTR_PERMANENT
,
840 CssmError::throwMe(status
);
842 if (descriptiveData
.Data
!= NULL
)
843 free (descriptiveData
.Data
);
845 freePrivateKey
= true;
847 // Find the keys we just generated in the DL to get SecKeyRefs to them
848 // so we can change the label to be the hash of the public key, and
849 // fix up other attributes.
851 // Look up public key in the DLDB.
852 DbAttributes pubDbAttributes
;
853 DbUniqueRecord pubUniqueId
;
854 SSDbCursor
dbPubCursor(ssDb
, 1);
855 dbPubCursor
->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY
);
856 dbPubCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, pubKeyHash
);
857 CssmClient::Key publicKey
;
858 if (!dbPubCursor
->nextKey(&pubDbAttributes
, publicKey
, pubUniqueId
))
859 MacOSError::throwMe(errSecItemNotFound
);
861 // Look up private key in the DLDB.
862 DbAttributes privDbAttributes
;
863 DbUniqueRecord privUniqueId
;
864 SSDbCursor
dbPrivCursor(ssDb
, 1);
865 dbPrivCursor
->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY
);
866 dbPrivCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, pubKeyHash
);
867 CssmClient::Key privateKey
;
868 if (!dbPrivCursor
->nextKey(&privDbAttributes
, privateKey
, privUniqueId
))
869 MacOSError::throwMe(errSecItemNotFound
);
871 // @@@ Not exception safe!
872 csp
.allocator().free(cssmData
->Data
);
873 csp
.allocator().free(cssmData
);
875 auto_ptr
<string
>privDescription
;
876 auto_ptr
<string
>pubDescription
;
878 privDescription
.reset(new string(initialAccess
->promptDescription()));
879 pubDescription
.reset(new string(initialAccess
->promptDescription()));
882 /* this path taken if no promptDescription available, e.g., for complex ACLs */
883 privDescription
.reset(new string("Private key"));
884 pubDescription
.reset(new string("Public key"));
887 // Set the label of the public key to the public key hash.
888 // Set the PrintName of the public key to the description in the acl.
889 pubDbAttributes
.add(kInfoKeyPrintName
, *pubDescription
);
890 pubUniqueId
->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY
, &pubDbAttributes
, NULL
, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
892 // Set the label of the private key to the public key hash.
893 // Set the PrintName of the private key to the description in the acl.
894 privDbAttributes
.add(kInfoKeyPrintName
, *privDescription
);
895 privUniqueId
->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY
, &privDbAttributes
, NULL
, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
897 // Finally fix the acl and owner of the private key to the specified access control settings.
898 initialAccess
->setAccess(*privateKey
, maker
);
900 // Make the public key acl completely open
901 SecPointer
<Access
> pubKeyAccess(new Access());
902 pubKeyAccess
->setAccess(*publicKey
, maker
);
904 // Create keychain items which will represent the keys.
905 publicKeyItem
= keychain
->item(CSSM_DL_DB_RECORD_PUBLIC_KEY
, pubUniqueId
);
906 privateKeyItem
= keychain
->item(CSSM_DL_DB_RECORD_PRIVATE_KEY
, privUniqueId
);
908 KeyItem
* impl
= dynamic_cast<KeyItem
*>(&(*publicKeyItem
));
911 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
916 impl
= dynamic_cast<KeyItem
*>(&(*privateKeyItem
));
919 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
921 outPrivateKey
= impl
;
926 CSSM_FreeKey(csp
->handle(), cred
, &publicCssmKey
, TRUE
);
928 CSSM_FreeKey(csp
->handle(), cred
, &privateCssmKey
, TRUE
);
931 CSSM_DeleteContext(ccHandle
);
937 CSSM_FreeKey(csp
->handle(), cred
, &publicCssmKey
, FALSE
);
939 CSSM_FreeKey(csp
->handle(), cred
, &privateCssmKey
, FALSE
);
942 CSSM_DeleteContext(ccHandle
);
944 if (keychain
&& publicKeyItem
&& privateKeyItem
)
946 KCEventNotifier::PostKeychainEvent(kSecAddEvent
, keychain
, publicKeyItem
);
947 KCEventNotifier::PostKeychainEvent(kSecAddEvent
, keychain
, privateKeyItem
);
952 KeyItem::generateWithAttributes(const SecKeychainAttributeList
*attrList
,
954 CSSM_ALGORITHMS algorithm
,
955 uint32 keySizeInBits
,
956 CSSM_CC_HANDLE contextHandle
,
957 CSSM_KEYUSE keyUsage
,
959 SecPointer
<Access
> initialAccess
)
961 CssmClient::CSP
appleCsp(gGuidAppleCSP
);
962 CssmClient::CSP
csp(NULL
);
964 uint8 labelBytes
[20];
965 CssmData
label(labelBytes
, sizeof(labelBytes
));
966 bool freeKey
= false;
967 bool deleteContext
= false;
968 const CSSM_DATA
*plabel
= NULL
;
972 if (!(keychain
->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP
))
973 MacOSError::throwMe(errSecInvalidKeychain
);
975 SSDbImpl
* impl
= dynamic_cast<SSDbImpl
*>(&(*keychain
->database()));
978 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
982 csp
= keychain
->csp();
984 // Generate a random label to use initially
985 CssmClient::Random
random(appleCsp
, CSSM_ALGID_APPLE_YARROW
);
986 random
.generate(label
, label
.Length
);
991 // Not a persistent key so create it in the regular csp
995 // Create a Access::Maker for the initial owner of the private key.
996 ResourceControlContext
*prcc
= NULL
, rcc
;
997 const AccessCredentials
*cred
= NULL
;
999 if (keychain
&& initialAccess
)
1001 memset(&rcc
, 0, sizeof(rcc
));
1002 // @@@ Potentially provide a credential argument which allows us to generate keys in the csp.
1003 // Currently the CSP lets anyone do this, but we might restrict this in the future, e.g. a smartcard
1004 // could require out-of-band pin entry before a key can be generated.
1005 maker
.initialOwner(rcc
);
1006 // Create the cred we need to manipulate the keys until we actually set a new access control for them.
1007 cred
= maker
.cred();
1013 CSSM_CC_HANDLE ccHandle
= 0;
1020 ccHandle
= contextHandle
;
1023 status
= CSSM_CSP_CreateKeyGenContext(csp
->handle(), algorithm
, keySizeInBits
, NULL
, NULL
, NULL
, NULL
, NULL
, &ccHandle
);
1025 CssmError::throwMe(status
);
1026 deleteContext
= true;
1031 CSSM_DL_DB_HANDLE dldbHandle
= ssDb
->handle();
1032 CSSM_DL_DB_HANDLE_PTR dldbHandlePtr
= &dldbHandle
;
1033 CSSM_CONTEXT_ATTRIBUTE contextAttributes
= { CSSM_ATTRIBUTE_DL_DB_HANDLE
, sizeof(dldbHandle
), { (char *)dldbHandlePtr
} };
1034 status
= CSSM_UpdateContextAttributes(ccHandle
, 1, &contextAttributes
);
1036 CssmError::throwMe(status
);
1038 keyAttr
|= CSSM_KEYATTR_PERMANENT
;
1042 status
= CSSM_GenerateKey(ccHandle
, keyUsage
, keyAttr
, plabel
, prcc
, &cssmKey
);
1044 CssmError::throwMe(status
);
1049 // Find the key we just generated in the DL and get a SecKeyRef
1050 // so we can specify the label attribute(s) and initial ACL.
1052 // Look up key in the DLDB.
1053 DbAttributes dbAttributes
;
1054 DbUniqueRecord uniqueId
;
1055 SSDbCursor
dbCursor(ssDb
, 1);
1056 dbCursor
->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
);
1057 dbCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, label
);
1058 CssmClient::Key key
;
1059 if (!dbCursor
->nextKey(&dbAttributes
, key
, uniqueId
))
1060 MacOSError::throwMe(errSecItemNotFound
);
1062 // Set the initial label, application label, and application tag (if provided)
1064 DbAttributes newDbAttributes
;
1065 SSDbCursor
otherDbCursor(ssDb
, 1);
1066 otherDbCursor
->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
);
1067 bool checkForDuplicates
= false;
1069 for (UInt32 index
=0; index
< attrList
->count
; index
++) {
1070 SecKeychainAttribute attr
= attrList
->attr
[index
];
1071 CssmData
attrData(attr
.data
, attr
.length
);
1072 if (attr
.tag
== kSecKeyPrintName
) {
1073 newDbAttributes
.add(kInfoKeyPrintName
, attrData
);
1075 if (attr
.tag
== kSecKeyLabel
) {
1076 newDbAttributes
.add(kInfoKeyLabel
, attrData
);
1077 otherDbCursor
->add(CSSM_DB_EQUAL
, kInfoKeyLabel
, attrData
);
1078 checkForDuplicates
= true;
1080 if (attr
.tag
== kSecKeyApplicationTag
) {
1081 newDbAttributes
.add(kInfoKeyApplicationTag
, attrData
);
1082 otherDbCursor
->add(CSSM_DB_EQUAL
, kInfoKeyApplicationTag
, attrData
);
1083 checkForDuplicates
= true;
1087 DbAttributes otherDbAttributes
;
1088 DbUniqueRecord otherUniqueId
;
1089 CssmClient::Key otherKey
;
1090 if (checkForDuplicates
&& otherDbCursor
->nextKey(&otherDbAttributes
, otherKey
, otherUniqueId
))
1091 MacOSError::throwMe(errSecDuplicateItem
);
1093 uniqueId
->modify(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
, &newDbAttributes
, NULL
, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
1096 // Finally, fix the acl and owner of the key to the specified access control settings.
1098 initialAccess
->setAccess(*key
, maker
);
1100 // Create keychain item which will represent the key.
1101 keyItem
= keychain
->item(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
, uniqueId
);
1105 CssmClient::Key
tempKey(csp
, cssmKey
);
1106 keyItem
= new KeyItem(tempKey
);
1113 // Delete the key if something goes wrong so we don't end up with inaccessible keys in the database.
1114 CSSM_FreeKey(csp
->handle(), cred
, &cssmKey
, TRUE
);
1118 CSSM_DeleteContext(ccHandle
);
1125 CSSM_FreeKey(csp
->handle(), NULL
, &cssmKey
, FALSE
);
1129 CSSM_DeleteContext(ccHandle
);
1131 if (keychain
&& keyItem
)
1132 keychain
->postEvent(kSecAddEvent
, keyItem
);
1134 KeyItem
* item
= dynamic_cast<KeyItem
*>(&*keyItem
);
1137 CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER
);
1144 KeyItem::generate(Keychain keychain
,
1145 CSSM_ALGORITHMS algorithm
,
1146 uint32 keySizeInBits
,
1147 CSSM_CC_HANDLE contextHandle
,
1148 CSSM_KEYUSE keyUsage
,
1150 SecPointer
<Access
> initialAccess
)
1152 return KeyItem::generateWithAttributes(NULL
, keychain
,
1153 algorithm
, keySizeInBits
, contextHandle
,
1154 keyUsage
, keyAttr
, initialAccess
);
1158 void KeyItem::RawSign(SecPadding padding
, CSSM_DATA dataToSign
, const AccessCredentials
*credentials
, CSSM_DATA
& signature
)
1160 CSSM_ALGORITHMS baseAlg
= key()->header().algorithm();
1161 if ((baseAlg
!= CSSM_ALGID_RSA
) && (baseAlg
!= CSSM_ALGID_ECDSA
))
1163 MacOSError::throwMe(paramErr
);
1166 CSSM_ALGORITHMS paddingAlg
= CSSM_PADDING_PKCS1
;
1170 case kSecPaddingPKCS1
:
1172 paddingAlg
= CSSM_PADDING_PKCS1
;
1176 case kSecPaddingPKCS1MD2
:
1178 baseAlg
= CSSM_ALGID_MD2WithRSA
;
1182 case kSecPaddingPKCS1MD5
:
1184 baseAlg
= CSSM_ALGID_MD5WithRSA
;
1188 case kSecPaddingPKCS1SHA1
:
1190 baseAlg
= CSSM_ALGID_SHA1WithRSA
;
1196 paddingAlg
= CSSM_PADDING_NONE
;
1201 Sign
signContext(csp(), baseAlg
);
1202 signContext
.key(key());
1203 signContext
.set(CSSM_ATTRIBUTE_PADDING
, paddingAlg
);
1204 signContext
.cred(credentials
);
1206 CssmData
data(dataToSign
.Data
, dataToSign
.Length
);
1207 signContext
.sign(data
);
1209 CssmData
sig(signature
.Data
, signature
.Length
);
1210 signContext(sig
); // yes, this is an accessor. Believe it, or not.
1211 signature
.Length
= sig
.length();
1216 void KeyItem::RawVerify(SecPadding padding
, CSSM_DATA dataToVerify
, const AccessCredentials
*credentials
, CSSM_DATA sig
)
1218 CSSM_ALGORITHMS baseAlg
= key()->header().algorithm();
1219 if ((baseAlg
!= CSSM_ALGID_RSA
) && (baseAlg
!= CSSM_ALGID_ECDSA
))
1221 MacOSError::throwMe(paramErr
);
1224 CSSM_ALGORITHMS paddingAlg
= CSSM_PADDING_PKCS1
;
1228 case kSecPaddingPKCS1
:
1230 paddingAlg
= CSSM_PADDING_PKCS1
;
1234 case kSecPaddingPKCS1MD2
:
1236 baseAlg
= CSSM_ALGID_MD2WithRSA
;
1240 case kSecPaddingPKCS1MD5
:
1242 baseAlg
= CSSM_ALGID_MD5WithRSA
;
1246 case kSecPaddingPKCS1SHA1
:
1248 baseAlg
= CSSM_ALGID_SHA1WithRSA
;
1254 paddingAlg
= CSSM_PADDING_NONE
;
1259 Verify
verifyContext(csp(), baseAlg
);
1260 verifyContext
.key(key());
1261 verifyContext
.set(CSSM_ATTRIBUTE_PADDING
, paddingAlg
);
1262 verifyContext
.cred(credentials
);
1264 CssmData
data(dataToVerify
.Data
, dataToVerify
.Length
);
1265 CssmData
signature(sig
.Data
, sig
.Length
);
1266 verifyContext
.verify(data
, signature
);
1271 void KeyItem::Encrypt(SecPadding padding
, CSSM_DATA dataToEncrypt
, const AccessCredentials
*credentials
, CSSM_DATA
& encryptedData
)
1273 CSSM_ALGORITHMS baseAlg
= key()->header().algorithm();
1274 if (baseAlg
!= CSSM_ALGID_RSA
)
1276 MacOSError::throwMe(paramErr
);
1279 CSSM_ALGORITHMS paddingAlg
= CSSM_PADDING_PKCS1
;
1283 case kSecPaddingPKCS1
:
1285 paddingAlg
= CSSM_PADDING_PKCS1
;
1291 paddingAlg
= CSSM_PADDING_NONE
;
1296 CssmClient::Encrypt
encryptContext(csp(), baseAlg
);
1297 encryptContext
.key(key());
1298 encryptContext
.padding(paddingAlg
);
1299 encryptContext
.cred(credentials
);
1301 CssmData
inData(dataToEncrypt
.Data
, dataToEncrypt
.Length
);
1302 CssmData
outData(encryptedData
.Data
, encryptedData
.Length
);
1303 CssmData
remData((void*) NULL
, 0);
1305 encryptedData
.Length
= encryptContext
.encrypt(inData
, outData
, remData
);
1310 void KeyItem::Decrypt(SecPadding padding
, CSSM_DATA dataToDecrypt
, const AccessCredentials
*credentials
, CSSM_DATA
& decryptedData
)
1312 CSSM_ALGORITHMS baseAlg
= key()->header().algorithm();
1313 if (baseAlg
!= CSSM_ALGID_RSA
)
1315 MacOSError::throwMe(paramErr
);
1318 CSSM_ALGORITHMS paddingAlg
= CSSM_PADDING_PKCS1
;
1322 case kSecPaddingPKCS1
:
1324 paddingAlg
= CSSM_PADDING_PKCS1
;
1331 paddingAlg
= CSSM_PADDING_NONE
;
1336 CssmClient::Decrypt
decryptContext(csp(), baseAlg
);
1337 decryptContext
.key(key());
1338 decryptContext
.padding(paddingAlg
);
1339 decryptContext
.cred(credentials
);
1341 CssmData
inData(dataToDecrypt
.Data
, dataToDecrypt
.Length
);
1342 CssmData
outData(decryptedData
.Data
, decryptedData
.Length
);
1343 CssmData
remData((void*) NULL
, 0);
1344 decryptedData
.Length
= decryptContext
.decrypt(inData
, outData
, remData
);
1345 if (remData
.Data
!= NULL
)