2 * Copyright (c) 2000-2006,2013 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@
26 // dbcrypto - cryptographic core for database and key blob cryptography
29 #include "SecRandom.h"
30 #include <security_utilities/casts.h>
31 #include <securityd_client/ssblob.h>
32 #include "server.h" // just for Server::csp()
33 #include <security_cdsa_client/genkey.h>
34 #include <security_cdsa_client/cryptoclient.h>
35 #include <security_cdsa_client/keyclient.h>
36 #include <security_cdsa_client/macclient.h>
37 #include <security_cdsa_client/wrapkey.h>
38 #include <security_cdsa_utilities/cssmendian.h>
40 using namespace CssmClient
;
41 using LowLevelMemoryUtilities::fieldOffsetOf
;
45 // The CryptoCore constructor doesn't do anything interesting.
46 // It just initializes us to "empty".
48 DatabaseCryptoCore::DatabaseCryptoCore(uint32 requestedVersion
) : mBlobVersion(CommonBlob::version_MacOS_10_0
), mHaveMaster(false), mIsValid(false)
50 // If there's a specific version our callers want, give them that. Otherwise, ask CommonBlob what to do.
51 if(requestedVersion
== CommonBlob::version_none
) {
52 mBlobVersion
= CommonBlob::getCurrentVersion();
54 mBlobVersion
= requestedVersion
;
58 DatabaseCryptoCore::~DatabaseCryptoCore()
60 // key objects take care of themselves
67 void DatabaseCryptoCore::invalidate()
72 mEncryptionKey
.release();
73 mSigningKey
.release();
78 // Copy everything from another databasecryptocore
80 void DatabaseCryptoCore::initializeFrom(DatabaseCryptoCore
& core
, uint32 requestedVersion
) {
81 if(core
.hasMaster()) {
82 mMasterKey
= core
.mMasterKey
;
83 memcpy(mSalt
, core
.mSalt
, sizeof(mSalt
));
84 mHaveMaster
= core
.mHaveMaster
;
95 // As the last thing we do, check if we should be changing the version of this blob.
96 if(requestedVersion
== CommonBlob::version_none
) {
97 mBlobVersion
= core
.mBlobVersion
;
99 mBlobVersion
= requestedVersion
;
104 // Generate new secrets for this crypto core.
106 void DatabaseCryptoCore::generateNewSecrets()
108 // create a random DES3 key
109 GenerateKey
desGenerator(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE
, 24 * 8);
110 mEncryptionKey
= desGenerator(KeySpec(CSSM_KEYUSE_WRAP
| CSSM_KEYUSE_UNWRAP
,
111 CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
));
113 // create a random 20 byte HMAC/SHA1 signing "key"
114 GenerateKey
signGenerator(Server::csp(), CSSM_ALGID_SHA1HMAC
,
115 sizeof(DbBlob::PrivateBlob::SigningKey
) * 8);
116 mSigningKey
= signGenerator(KeySpec(CSSM_KEYUSE_SIGN
| CSSM_KEYUSE_VERIFY
,
117 CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
));
119 // secrets established
124 CssmClient::Key
DatabaseCryptoCore::masterKey()
132 // Establish the master secret as derived from a passphrase passed in.
133 // If a DbBlob is passed, take the salt from it and remember it.
134 // If a NULL DbBlob is passed, generate a new (random) salt.
135 // Note that the passphrase is NOT remembered; only the master key.
137 void DatabaseCryptoCore::setup(const DbBlob
*blob
, const CssmData
&passphrase
, bool copyVersion
/* = true */)
141 mBlobVersion
= blob
->version();
143 memcpy(mSalt
, blob
->salt
, sizeof(mSalt
));
145 MacOSError::check(SecRandomCopyBytes(kSecRandomDefault
, sizeof(mSalt
), mSalt
));
148 mMasterKey
= deriveDbMasterKey(passphrase
);
154 // Establish the master secret directly from a master key passed in.
155 // We will copy the KeyData (caller still owns its copy).
156 // Blob/salt handling as above.
158 void DatabaseCryptoCore::setup(const DbBlob
*blob
, CssmClient::Key master
, bool copyVersion
/* = true */)
160 // pre-screen the key
161 CssmKey::Header header
= master
.header();
162 if (header
.keyClass() != CSSM_KEYCLASS_SESSION_KEY
)
163 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
164 if (header
.algorithm() != CSSM_ALGID_3DES_3KEY_EDE
)
165 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
170 mBlobVersion
= blob
->version();
172 memcpy(mSalt
, blob
->salt
, sizeof(mSalt
));
174 MacOSError::check(SecRandomCopyBytes(kSecRandomDefault
, sizeof(mSalt
), mSalt
));
180 bool DatabaseCryptoCore::get_encryption_key(CssmOwnedData
&data
)
184 data
= mEncryptionKey
->keyData();
191 // Given a putative passphrase, determine whether that passphrase
192 // properly generates the database's master secret.
193 // Return a boolean accordingly. Do not change our state.
194 // The database must have a master secret (to compare with).
195 // Note that any errors thrown by the cryptography here will actually
196 // throw out of validatePassphrase, since they "should not happen" and
197 // thus indicate a problem *beyond* (just) a bad passphrase.
199 bool DatabaseCryptoCore::validatePassphrase(const CssmData
&passphrase
)
201 CssmClient::Key master
= deriveDbMasterKey(passphrase
);
202 return validateKey(master
);
205 bool DatabaseCryptoCore::validateKey(const CssmClient::Key
& master
) {
207 // to compare master with mMaster, see if they encrypt alike
209 ("Now is the time for all good processes to come to the aid of their kernel.");
210 CssmData
noRemainder((void *)1, 0); // no cipher overflow
211 Encrypt
cryptor(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE
);
212 cryptor
.mode(CSSM_ALGMODE_CBCPadIV8
);
213 cryptor
.padding(CSSM_PADDING_PKCS1
);
214 uint8 iv
[8]; // leave uninitialized; pseudo-random is cool
215 CssmData ivData
= CssmData::wrap(iv
);
216 cryptor
.initVector(ivData
);
219 CssmAutoData
cipher1(Server::csp().allocator());
220 cryptor
.encrypt(probe
, cipher1
.get(), noRemainder
);
222 cryptor
.key(mMasterKey
);
223 CssmAutoData
cipher2(Server::csp().allocator());
224 cryptor
.encrypt(probe
, cipher2
.get(), noRemainder
);
226 return cipher1
== cipher2
;
231 // Encode a database blob from the core.
233 DbBlob
*DatabaseCryptoCore::encodeCore(const DbBlob
&blobTemplate
,
234 const CssmData
&publicAcl
, const CssmData
&privateAcl
) const
236 assert(isValid()); // must have secrets to work from
240 MacOSError::check(SecRandomCopyBytes(kSecRandomDefault
, sizeof(iv
), iv
));
242 // build the encrypted section blob
243 CssmData
&encryptionBits
= *mEncryptionKey
;
244 CssmData
&signingBits
= *mSigningKey
;
246 incrypt
[0] = encryptionBits
;
247 incrypt
[1] = signingBits
;
248 incrypt
[2] = privateAcl
;
249 CssmData cryptoBlob
, remData
;
250 Encrypt
cryptor(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE
);
251 cryptor
.mode(CSSM_ALGMODE_CBCPadIV8
);
252 cryptor
.padding(CSSM_PADDING_PKCS1
);
253 cryptor
.key(mMasterKey
);
254 CssmData
ivd(iv
, sizeof(iv
)); cryptor
.initVector(ivd
);
255 cryptor
.encrypt(incrypt
, 3, &cryptoBlob
, 1, remData
);
257 // allocate the final DbBlob, uh, blob
258 size_t length
= sizeof(DbBlob
) + publicAcl
.length() + cryptoBlob
.length();
259 DbBlob
*blob
= Allocator::standard().malloc
<DbBlob
>(length
);
261 // assemble the DbBlob
262 memset(blob
, 0x7d, sizeof(DbBlob
)); // deterministically fill any alignment gaps
263 blob
->initialize(mBlobVersion
);
264 blob
->randomSignature
= blobTemplate
.randomSignature
;
265 blob
->sequence
= blobTemplate
.sequence
;
266 blob
->params
= blobTemplate
.params
;
267 memcpy(blob
->salt
, mSalt
, sizeof(blob
->salt
));
268 memcpy(blob
->iv
, iv
, sizeof(iv
));
269 memcpy(blob
->publicAclBlob(), publicAcl
, publicAcl
.length());
270 blob
->startCryptoBlob
= sizeof(DbBlob
) + int_cast
<size_t, uint32_t>(publicAcl
.length());
271 memcpy(blob
->cryptoBlob(), cryptoBlob
, cryptoBlob
.length());
272 blob
->totalLength
= blob
->startCryptoBlob
+ int_cast
<size_t, uint32_t>(cryptoBlob
.length());
275 CssmData signChunk
[] = {
276 CssmData(blob
->data(), fieldOffsetOf(&DbBlob::blobSignature
)),
277 CssmData(blob
->publicAclBlob(), publicAcl
.length() + cryptoBlob
.length())
279 CssmData
signature(blob
->blobSignature
, sizeof(blob
->blobSignature
));
281 CSSM_ALGORITHMS signingAlgorithm
= CSSM_ALGID_SHA1HMAC
;
282 #if defined(COMPAT_OSX_10_0)
283 if (blob
->version() == blob
->version_MacOS_10_0
)
284 signingAlgorithm
= CSSM_ALGID_SHA1HMAC_LEGACY
; // BSafe bug compatibility
286 GenerateMac
signer(Server::csp(), signingAlgorithm
);
287 signer
.key(mSigningKey
);
288 signer
.sign(signChunk
, 2, signature
);
289 assert(signature
.length() == sizeof(blob
->blobSignature
));
291 // all done. Clean up
292 Server::csp()->allocator().free(cryptoBlob
);
298 // Decode a database blob into the core.
299 // Throws exceptions if decoding fails.
300 // Memory returned in privateAclBlob is allocated and becomes owned by caller.
302 void DatabaseCryptoCore::decodeCore(const DbBlob
*blob
, void **privateAclBlob
)
304 assert(mHaveMaster
); // must have master key installed
306 // try to decrypt the cryptoblob section
307 Decrypt
decryptor(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE
);
308 decryptor
.mode(CSSM_ALGMODE_CBCPadIV8
);
309 decryptor
.padding(CSSM_PADDING_PKCS1
);
310 decryptor
.key(mMasterKey
);
311 CssmData ivd
= CssmData::wrap(blob
->iv
); decryptor
.initVector(ivd
);
312 CssmData cryptoBlob
= CssmData::wrap(blob
->cryptoBlob(), blob
->cryptoBlobLength());
313 CssmData decryptedBlob
, remData
;
314 decryptor
.decrypt(cryptoBlob
, decryptedBlob
, remData
);
315 DbBlob::PrivateBlob
*privateBlob
= decryptedBlob
.interpretedAs
<DbBlob::PrivateBlob
>();
317 // tentatively establish keys
318 mEncryptionKey
= makeRawKey(privateBlob
->encryptionKey
,
319 sizeof(privateBlob
->encryptionKey
), CSSM_ALGID_3DES_3KEY_EDE
,
320 CSSM_KEYUSE_WRAP
| CSSM_KEYUSE_UNWRAP
);
321 mSigningKey
= makeRawKey(privateBlob
->signingKey
,
322 sizeof(privateBlob
->signingKey
), CSSM_ALGID_SHA1HMAC
,
323 CSSM_KEYUSE_SIGN
| CSSM_KEYUSE_VERIFY
);
325 // verify signature on the whole blob
326 CssmData signChunk
[] = {
327 CssmData::wrap(blob
->data(), fieldOffsetOf(&DbBlob::blobSignature
)),
328 CssmData::wrap(blob
->publicAclBlob(), blob
->publicAclBlobLength() + blob
->cryptoBlobLength())
330 CSSM_ALGORITHMS verifyAlgorithm
= CSSM_ALGID_SHA1HMAC
;
331 #if defined(COMPAT_OSX_10_0)
332 if (blob
->version() == blob
->version_MacOS_10_0
)
333 verifyAlgorithm
= CSSM_ALGID_SHA1HMAC_LEGACY
; // BSafe bug compatibility
335 VerifyMac
verifier(Server::csp(), verifyAlgorithm
);
336 verifier
.key(mSigningKey
);
337 verifier
.verify(signChunk
, 2, CssmData::wrap(blob
->blobSignature
));
339 // all checks out; start extracting fields
340 if (privateAclBlob
) {
341 // extract private ACL blob as a separately allocated area
342 uint32 blobLength
= (uint32
) decryptedBlob
.length() - sizeof(DbBlob::PrivateBlob
);
343 *privateAclBlob
= Allocator::standard().malloc(blobLength
);
344 memcpy(*privateAclBlob
, privateBlob
->privateAclBlob(), blobLength
);
347 // secrets have been established
348 mBlobVersion
= blob
->version();
350 Allocator::standard().free(privateBlob
);
355 // Make another DatabaseCryptoCore's operational secrets our own.
356 // Intended for keychain synchronization.
358 void DatabaseCryptoCore::importSecrets(const DatabaseCryptoCore
&src
)
360 assert(src
.isValid()); // must have called src.decodeCore() first
362 mEncryptionKey
= src
.mEncryptionKey
;
363 mSigningKey
= src
.mSigningKey
;
364 mBlobVersion
= src
.mBlobVersion
; // make sure we copy over all state
371 KeyBlob
*DatabaseCryptoCore::encodeKeyCore(const CssmKey
&inKey
,
372 const CssmData
&publicAcl
, const CssmData
&privateAcl
,
373 bool inTheClear
) const
379 if(inTheClear
&& (privateAcl
.Length
!= 0)) {
380 /* can't store private ACL component in the clear */
381 CssmError::throwMe(CSSMERR_DL_INVALID_ACCESS_CREDENTIALS
);
384 // extract and hold some header bits the CSP does not want to see
385 uint32 heldAttributes
= key
.attributes() & managedAttributes
;
386 key
.clearAttribute(managedAttributes
);
387 key
.setAttribute(forcedAttributes
);
390 /* NULL wrap of public key */
391 WrapKey
wrap(Server::csp(), CSSM_ALGID_NONE
);
392 wrap(key
, wrappedKey
, NULL
);
395 assert(isValid()); // need our database secrets
398 MacOSError::check(SecRandomCopyBytes(kSecRandomDefault
, sizeof(iv
), iv
));
400 // use a CMS wrap to encrypt the key
401 WrapKey
wrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE
);
402 wrap
.key(mEncryptionKey
);
403 wrap
.mode(CSSM_ALGMODE_CBCPadIV8
);
404 wrap
.padding(CSSM_PADDING_PKCS1
);
405 CssmData
ivd(iv
, sizeof(iv
)); wrap
.initVector(ivd
);
406 wrap
.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT
,
407 uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
));
408 wrap(key
, wrappedKey
, &privateAcl
);
411 // stick the held attribute bits back in
412 key
.clearAttribute(forcedAttributes
);
413 key
.setAttribute(heldAttributes
);
415 // allocate the final KeyBlob, uh, blob
416 size_t length
= sizeof(KeyBlob
) + publicAcl
.length() + wrappedKey
.length();
417 KeyBlob
*blob
= Allocator::standard().malloc
<KeyBlob
>(length
);
419 // assemble the KeyBlob
420 memset(blob
, 0, sizeof(KeyBlob
)); // fill alignment gaps
421 blob
->initialize(mBlobVersion
);
423 memcpy(blob
->iv
, iv
, sizeof(iv
));
425 blob
->header
= key
.header();
426 h2ni(blob
->header
); // endian-correct the header
427 blob
->wrappedHeader
.blobType
= wrappedKey
.blobType();
428 blob
->wrappedHeader
.blobFormat
= wrappedKey
.blobFormat();
429 blob
->wrappedHeader
.wrapAlgorithm
= wrappedKey
.wrapAlgorithm();
430 blob
->wrappedHeader
.wrapMode
= wrappedKey
.wrapMode();
431 memcpy(blob
->publicAclBlob(), publicAcl
, publicAcl
.length());
432 blob
->startCryptoBlob
= sizeof(KeyBlob
) + int_cast
<size_t, uint32_t>(publicAcl
.length());
433 memcpy(blob
->cryptoBlob(), wrappedKey
.data(), wrappedKey
.length());
434 blob
->totalLength
= blob
->startCryptoBlob
+ int_cast
<size_t, uint32_t>(wrappedKey
.length());
437 /* indicate that this is cleartext for decoding */
438 blob
->setClearTextSignature();
442 CssmData signChunk
[] = {
443 CssmData(blob
->data(), fieldOffsetOf(&KeyBlob::blobSignature
)),
444 CssmData(blob
->publicAclBlob(), blob
->publicAclBlobLength() + blob
->cryptoBlobLength())
446 CssmData
signature(blob
->blobSignature
, sizeof(blob
->blobSignature
));
448 CSSM_ALGORITHMS signingAlgorithm
= CSSM_ALGID_SHA1HMAC
;
449 #if defined(COMPAT_OSX_10_0)
450 if (blob
->version() == blob
->version_MacOS_10_0
)
451 signingAlgorithm
= CSSM_ALGID_SHA1HMAC_LEGACY
; // BSafe bug compatibility
453 GenerateMac
signer(Server::csp(), signingAlgorithm
);
454 signer
.key(mSigningKey
);
455 signer
.sign(signChunk
, 2, signature
);
456 assert(signature
.length() == sizeof(blob
->blobSignature
));
459 // all done. Clean up
460 Server::csp()->allocator().free(wrappedKey
);
468 void DatabaseCryptoCore::decodeKeyCore(KeyBlob
*blob
,
469 CssmKey
&key
, void * &pubAcl
, void * &privAcl
) const
471 // Note that we can't do anything with this key's version().
473 // Assemble the encrypted blob as a CSSM "wrapped key"
475 wrappedKey
.KeyHeader
= blob
->header
;
476 h2ni(wrappedKey
.KeyHeader
);
477 wrappedKey
.blobType(blob
->wrappedHeader
.blobType
);
478 wrappedKey
.blobFormat(blob
->wrappedHeader
.blobFormat
);
479 wrappedKey
.wrapAlgorithm(blob
->wrappedHeader
.wrapAlgorithm
);
480 wrappedKey
.wrapMode(blob
->wrappedHeader
.wrapMode
);
481 wrappedKey
.KeyData
= CssmData(blob
->cryptoBlob(), blob
->cryptoBlobLength());
483 bool inTheClear
= blob
->isClearText();
485 // verify signature (check against corruption)
486 assert(isValid()); // need our database secrets
487 CssmData signChunk
[] = {
488 CssmData::wrap(blob
, fieldOffsetOf(&KeyBlob::blobSignature
)),
489 CssmData(blob
->publicAclBlob(), blob
->publicAclBlobLength() + blob
->cryptoBlobLength())
491 CSSM_ALGORITHMS verifyAlgorithm
= CSSM_ALGID_SHA1HMAC
;
492 #if defined(COMPAT_OSX_10_0)
493 if (blob
->version() == blob
->version_MacOS_10_0
)
494 verifyAlgorithm
= CSSM_ALGID_SHA1HMAC_LEGACY
; // BSafe bug compatibility
496 VerifyMac
verifier(Server::csp(), verifyAlgorithm
);
497 verifier
.key(mSigningKey
);
498 CssmData
signature(blob
->blobSignature
, sizeof(blob
->blobSignature
));
499 verifier
.verify(signChunk
, 2, signature
);
501 /* else signature indicates cleartext */
503 // extract and hold some header bits the CSP does not want to see
504 uint32 heldAttributes
= n2h(blob
->header
.attributes()) & managedAttributes
;
506 CssmData privAclData
;
509 UnwrapKey
unwrap(Server::csp(), CSSM_ALGID_NONE
);
510 wrappedKey
.clearAttribute(managedAttributes
); //@@@ shouldn't be needed(?)
512 KeySpec(n2h(blob
->header
.usage()),
513 (n2h(blob
->header
.attributes()) & ~managedAttributes
) | forcedAttributes
),
517 // decrypt the key using an unwrapping operation
518 UnwrapKey
unwrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE
);
519 unwrap
.key(mEncryptionKey
);
520 unwrap
.mode(CSSM_ALGMODE_CBCPadIV8
);
521 unwrap
.padding(CSSM_PADDING_PKCS1
);
522 CssmData
ivd(blob
->iv
, sizeof(blob
->iv
)); unwrap
.initVector(ivd
);
523 unwrap
.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT
,
524 uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM
));
525 wrappedKey
.clearAttribute(managedAttributes
); //@@@ shouldn't be needed(?)
527 KeySpec(n2h(blob
->header
.usage()),
528 (n2h(blob
->header
.attributes()) & ~managedAttributes
) | forcedAttributes
),
532 // compare retrieved key headers with blob headers (sanity check)
533 // @@@ this should probably be checked over carefully
534 CssmKey::Header
&real
= key
.header();
535 CssmKey::Header
&incoming
= blob
->header
;
538 if (real
.HeaderVersion
!= incoming
.HeaderVersion
||
539 real
.cspGuid() != incoming
.cspGuid())
540 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
541 if (real
.algorithm() != incoming
.algorithm())
542 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
544 // re-insert held bits
545 key
.header().KeyAttr
|= heldAttributes
;
547 if(inTheClear
&& (real
.keyClass() != CSSM_KEYCLASS_PUBLIC_KEY
)) {
548 /* Spoof - cleartext KeyBlob passed off as private key */
549 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
552 // got a valid key: return the pieces
553 pubAcl
= blob
->publicAclBlob(); // points into blob (shared)
554 privAcl
= privAclData
; // was allocated by CSP decrypt, else NULL for
556 // key was set by unwrap operation
561 // Derive the blob-specific database blob encryption key from the passphrase and the salt.
563 CssmClient::Key
DatabaseCryptoCore::deriveDbMasterKey(const CssmData
&passphrase
) const
565 // derive an encryption key and IV from passphrase and salt
566 CssmClient::DeriveKey
makeKey(Server::csp(),
567 CSSM_ALGID_PKCS5_PBKDF2
, CSSM_ALGID_3DES_3KEY_EDE
, 24 * 8);
568 makeKey
.iterationCount(1000);
569 CssmData salt
= CssmData::wrap(mSalt
);
571 CSSM_PKCS5_PBKDF2_PARAMS params
;
572 params
.Passphrase
= passphrase
;
573 params
.PseudoRandomFunction
= CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1
;
574 CssmData paramData
= CssmData::wrap(params
);
575 return makeKey(¶mData
, KeySpec(CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_DECRYPT
,
576 CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
));
581 // Turn raw keybits into a symmetric key in the CSP
583 CssmClient::Key
DatabaseCryptoCore::makeRawKey(void *data
, size_t length
,
584 CSSM_ALGORITHMS algid
, CSSM_KEYUSE usage
)
588 key
.header().BlobType
= CSSM_KEYBLOB_RAW
;
589 key
.header().Format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
590 key
.header().AlgorithmId
= algid
;
591 key
.header().KeyClass
= CSSM_KEYCLASS_SESSION_KEY
;
592 key
.header().KeyUsage
= usage
;
593 key
.header().KeyAttr
= 0;
594 key
.KeyData
= CssmData(data
, length
);
596 // unwrap it into the CSP (but keep it raw)
597 UnwrapKey
unwrap(Server::csp(), CSSM_ALGID_NONE
);
598 CssmKey unwrappedKey
;
599 CssmData descriptiveData
;
601 KeySpec(CSSM_KEYUSE_ANY
, CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
),
602 unwrappedKey
, &descriptiveData
, NULL
);
603 return CssmClient::Key(Server::csp(), unwrappedKey
);