/* * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST * passthrough. */ bool RSAKeyInfoProvider::getHashableBlob( Allocator &allocator, CssmData &blob) // blob to hash goes here { /* * The optimized case, a raw key in the "proper" format already. * Only public keys in PKCS1 format fit this bill. */ assert(mKey.blobType() == CSSM_KEYBLOB_RAW); bool useAsIs = false; switch(mKey.keyClass()) { case CSSM_KEYCLASS_PUBLIC_KEY: if(mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { useAsIs = true; } break; case CSSM_KEYCLASS_PRIVATE_KEY: break; default: /* shouldn't be here */ assert(0); CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); } if(useAsIs) { const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); copyCssmData(keyBlob, blob, allocator); return true; } /* caller converts to binary and proceeds */ return false; }
void copyData( const CSSM_DATA &src, CSSM_DATA &dst, Allocator &allocator) { copyCssmData(CssmData::overlay(src), CssmData::overlay(dst), allocator); }
/* * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST * passthrough. */ bool SymmetricKeyInfoProvider::getHashableBlob( Allocator &allocator, CssmData &blob) // blob to hash goes here { /* * This is trivial: the raw key is already in the "proper" format. */ assert(mKey.blobType() == CSSM_KEYBLOB_RAW); const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); copyCssmData(keyBlob, blob, allocator); return true; }
/* * Generate keygen parameters, stash them in a context attr array for later use * when actually generating the keys. */ void DSAKeyPairGenContext::generate( const Context &context, uint32 bitSize, CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs) { void *seed = NULL; unsigned seedLen = 0; /* optional seed from context */ CssmData *seedData = context.get<CssmData>(CSSM_ATTRIBUTE_SEED); if(seedData) { seed = seedData->data(); seedLen = (unsigned)seedData->length(); } /* generate the params, temp alloc from SecNssCoder */ NSS_DSAAlgParams algParams; SecNssCoder coder; dsaGenParams(bitSize, seed, seedLen, algParams, coder); /* * Here comes the fun part. * We "return" the DER encoding of these generated params in two ways: * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL. * The app must free this. * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr, * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to * this attr array and free it, the CSSM_DATA it points to, and the DER * encoding *that* points to, in our destructor. * * First, DER encode. */ CssmAutoData aDerData(session()); DSAEncodeAlgParams(algParams, aDerData); /* copy/release that into a mallocd CSSM_DATA. */ CSSM_DATA_PTR derData = (CSSM_DATA_PTR)session().malloc(sizeof(CSSM_DATA)); *derData = aDerData.release(); /* stuff that into a one-element Attr array which we keep after returning */ freeGenAttrs(); mGenAttrs = (Context::Attr *)session().malloc(sizeof(Context::Attr)); mGenAttrs->AttributeType = CSSM_ATTRIBUTE_ALG_PARAMS; mGenAttrs->AttributeLength = sizeof(CSSM_DATA); mGenAttrs->Attribute.Data = derData; /* and "return" this stuff */ copyCssmData(CssmData::overlay(*derData), params, session()); attrCount = 1; attrs = mGenAttrs; }
/* cook up a Binary key */ void SymmetricKeyInfoProvider::CssmKeyToBinary( CssmKey *paramKey, // ignored CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT BinaryKey **binKey) { CASSERT(mKey.keyClass() == CSSM_KEYCLASS_SESSION_KEY); SymmetricBinaryKey *symBinKey = new SymmetricBinaryKey( mKey.KeyHeader.LogicalKeySizeInBits); copyCssmData(mKey, symBinKey->mKeyData, symBinKey->mAllocator); *binKey = symBinKey; }
void SymmetricBinaryKey::generateKeyBlob( Allocator &allocator, CssmData &blob, CSSM_KEYBLOB_FORMAT &format, // CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc. AppleCSPSession &session, const CssmKey *paramKey, /* optional, unused here */ CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ { switch(format) { case CSSM_KEYBLOB_RAW_FORMAT_NONE: // default case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: // the one we can do case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: // same thing break; default: CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT); } copyCssmData(mKeyData, blob, allocator); format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; }
/* * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST * passthrough. */ bool CryptKit::FEEKeyInfoProvider::getHashableBlob( Allocator &allocator, CssmData &blob) // blob to hash goes here { /* * The optimized case, a raw key in the "proper" format already. * Currently this is: * FEE public key in default/NONE form (which happens to be DER) */ assert(mKey.blobType() == CSSM_KEYBLOB_RAW); if((mKey.algorithm() == CSSM_ALGID_FEE) && (mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_NONE) && (mKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY)) { const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); copyCssmData(keyBlob, blob, allocator); return true; } /* caller converts to binary and proceeds */ return false; }
void AppleCSPSession::WrapKey( CSSM_CC_HANDLE CCHandle, const Context &Context, const AccessCredentials &AccessCred, const CssmKey &UnwrappedKey, const CssmData *DescriptiveData, CssmKey &WrappedKey, CSSM_PRIVILEGE Privilege) { CssmKey::Header &wrappedHdr = WrappedKey.header(); bool isNullWrap = false; CssmKey *wrappingKey = NULL; CSSM_KEYBLOB_FORMAT wrapFormat; switch(UnwrappedKey.keyClass()) { case CSSM_KEYCLASS_PUBLIC_KEY: case CSSM_KEYCLASS_PRIVATE_KEY: case CSSM_KEYCLASS_SESSION_KEY: break; default: CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } /* wrapping key only required for non-NULL wrap */ wrappingKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_KEY); if(wrappingKey == NULL) { if((Context.algorithm() == CSSM_ALGID_NONE) && (Context.type() == CSSM_ALGCLASS_SYMMETRIC)) { // NULL wrap, OK isNullWrap = true; } else { errorLog0("WrapKey: missing wrapping key\n"); CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); } } /* * Validate misc. params as best we can */ if(isNullWrap) { wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; } else { /* * Can only wrap session and private keys. */ #if !ALLOW_PUB_KEY_WRAP if(UnwrappedKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } #endif /* ALLOW_PUB_KEY_WRAP */ cspValidateIntendedKeyUsage(&wrappingKey->KeyHeader, CSSM_KEYUSE_WRAP); cspVerifyKeyTimes(wrappingKey->KeyHeader); /* * make sure wrapping key type matches context */ CSSM_CONTEXT_TYPE wrapType; switch(wrappingKey->KeyHeader.KeyClass) { case CSSM_KEYCLASS_PUBLIC_KEY: case CSSM_KEYCLASS_PRIVATE_KEY: wrapType = CSSM_ALGCLASS_ASYMMETRIC; break; case CSSM_KEYCLASS_SESSION_KEY: wrapType = CSSM_ALGCLASS_SYMMETRIC; break; default: errorLog0("WrapKey: bad class of wrappingKey\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); } if(wrapType != Context.type()) { errorLog0("WrapKey: mismatch wrappingKey/contextType\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); } if(Context.algorithm() == CSSM_ALGID_NONE) { errorLog0("WrapKey: null wrap alg, non-null key\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } /* * Get optional wrap format, set default per incoming keys * Note: no such atrribute ==> 0 ==> FORMAT_NONE, which we * take to mean "use the default". */ wrapFormat = Context.getInt(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT); if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { /* figure out a default based on unwrapped key */ switch(UnwrappedKey.keyClass()) { case CSSM_KEYCLASS_SESSION_KEY: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; break; case CSSM_KEYCLASS_PUBLIC_KEY: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; break; case CSSM_KEYCLASS_PRIVATE_KEY: switch(UnwrappedKey.algorithm()) { case CSSM_ALGID_FEE: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; break; default: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; break; } break; default: /* NOT REACHED - checked above */ break; } } /* no format present or FORMAT_NONE */ } /* make sure we have a valid format here */ switch(wrapFormat) { case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7: if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_SESSION_KEY) { /* this wrapping style only for symmetric keys */ CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } break; case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { /* these wrapping styles only for private keys */ CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } break; case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: /* no restrictions (well AES can't be the wrap alg but that will * be caught later */ break; case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: /* RSA private key, reference format, only */ if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } if(UnwrappedKey.algorithm() != CSSM_ALGID_RSA) { CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } if(UnwrappedKey.blobType() != CSSM_KEYBLOB_REFERENCE) { CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); } break; case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE: if(isNullWrap) { /* only time this is OK */ break; } /* else fall thru */ default: dprintf1("KeyWrap: invalid wrapFormat (%d)\n", (int)wrapFormat); CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT); } /* get the blob to be wrappped */ CssmData rawBlob; bool allocdRawBlob = false; CSSM_KEYBLOB_FORMAT rawFormat; /* * Outgoing same as incoming unless a partial key is completed during * generateKeyBlob() */ const CssmKey::Header &unwrappedHdr = UnwrappedKey.header(); CSSM_KEYATTR_FLAGS unwrappedKeyAttrFlags = unwrappedHdr.KeyAttr; switch(UnwrappedKey.blobType()) { case CSSM_KEYBLOB_RAW: /* * Trivial case - we already have the blob. * This op - wrapping a raw key - is not supported for the * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1 format since that doesn't * operate on a key blob. */ rawBlob = CssmData::overlay(UnwrappedKey.KeyData); rawFormat = UnwrappedKey.blobFormat(); break; case CSSM_KEYBLOB_REFERENCE: /* get binary key, then get blob from it */ { BinaryKey &binKey = lookupRefKey(UnwrappedKey); /* * Subsequent tests for extractability: don't trust the * caller's header; use the one in the BinaryKey. */ CSSM_KEYATTR_FLAGS keyAttr = binKey.mKeyHeader.KeyAttr; if(!(keyAttr & CSSM_KEYATTR_EXTRACTABLE)) { /* this key not extractable in any form */ CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); } /* * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: we're ready to roll; * all we need is the reference key. */ if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1) { break; } /* * Null wrap - prevent caller from obtaining * clear bits if CSSM_KEYATTR_SENSITIVE */ if(isNullWrap && (keyAttr & CSSM_KEYATTR_SENSITIVE)) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); } /* * Special case for PKCS8 and openssl: need to get blob of a specific * algorithm-dependent format. Caller can override our * preference with a * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT * context attribute. */ rawFormat = requestedKeyFormat(Context, UnwrappedKey); if(rawFormat == CSSM_KEYBLOB_RAW_FORMAT_NONE) { CSSM_ALGORITHMS keyAlg = binKey.mKeyHeader.AlgorithmId; switch(wrapFormat) { case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: rawFormat = pkcs8RawKeyFormat(keyAlg); break; case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: rawFormat = opensslRawKeyFormat(keyAlg); break; default: /* punt and take default for key type */ break; } } /* * DescriptiveData for encoding, currently only used for * SSH1 keys. */ if((DescriptiveData != NULL) && (DescriptiveData->Length != 0)) { binKey.descData(*DescriptiveData); } /* optional parameter-bearing key */ CssmKey *paramKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_PARAM_KEY); binKey.generateKeyBlob(privAllocator, rawBlob, rawFormat, *this, paramKey, unwrappedKeyAttrFlags); } allocdRawBlob = true; // remember - we need to free break; default: errorLog0("WrapKey: bad unwrappedKey BlobType\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); } /* * Prepare outgoing header. */ setKeyHeader(wrappedHdr, plugin.myGuid(), unwrappedHdr.algorithm(), // same as incoming unwrappedHdr.keyClass(), // same as incoming unwrappedKeyAttrFlags, unwrappedHdr.KeyUsage); wrappedHdr.LogicalKeySizeInBits = unwrappedHdr.LogicalKeySizeInBits; wrappedHdr.WrapAlgorithmId = Context.algorithm(); // true for null // and non-Null wrappedHdr.StartDate = unwrappedHdr.StartDate; wrappedHdr.EndDate = unwrappedHdr.EndDate; wrappedHdr.Format = wrapFormat; if(isNullWrap) { wrappedHdr.BlobType = CSSM_KEYBLOB_RAW; } else { wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED; } /* * special cases - break out here for Apple Custom and OpenSSHv1 */ if(!isNullWrap) { switch(wrapFormat) { case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: try { WrapKeyCms(CCHandle, Context, AccessCred, UnwrappedKey, rawBlob, allocdRawBlob, DescriptiveData, WrappedKey, Privilege); } catch(...) { if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } throw; } if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } return; case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: { /* * 1. We don't have to worry about allocdRawBlob since this * operation only works on reference keys and we did not * obtain the raw blob from the BinaryKey. * 2. This is a redundant lookupRefKey, I know, but since * that returns a reference, it would just be too messy to have * the previous call be in the same scope as this. */ BinaryKey &binKey = lookupRefKey(UnwrappedKey); WrapKeyOpenSSH1(CCHandle, Context, AccessCred, binKey, rawBlob, allocdRawBlob, DescriptiveData, WrappedKey, Privilege); return; } default: /* proceed to encrypt blob */ break; } } /* !isNullWrap */ /* * Generate wrapped blob. Careful, we need to conditionally free * rawBlob on error. */ CssmData encryptedBlob; CssmData remData; WrappedKey.KeyData.Data = NULL; // ignore possible incoming KeyData WrappedKey.KeyData.Length = 0; try { if(isNullWrap) { /* copy raw blob to caller's wrappedKey */ copyCssmData(rawBlob, CssmData::overlay(WrappedKey.KeyData), normAllocator); wrappedHdr.Format = rawFormat; } else { /* encrypt rawBlob using caller's context, then encode to * WrappedKey.KeyData */ CSSM_SIZE bytesEncrypted; EncryptData(CCHandle, Context, &rawBlob, // ClearBufs[] 1, // ClearBufCount &encryptedBlob, // CipherBufs[], 1, // CipherBufCount, bytesEncrypted, remData, Privilege); // I'm not 100% sure about this.... assert(remData.Length == 0); encryptedBlob.Length = bytesEncrypted; WrappedKey.KeyData = encryptedBlob; wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED; // OK to be zero or not present wrappedHdr.WrapMode = Context.getInt( CSSM_ATTRIBUTE_MODE); } } catch (...) { errorLog0("WrapKey: EncryptData() threw exception\n"); if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } freeCssmData(remData,normAllocator); throw; } if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } freeCssmData(remData, normAllocator); }