Exemplo n.º 1
0
OSStatus cmsNullWrapKey(SecKeyRef refKey,
                               CSSM_KEY_PTR rawKey)
{
    CSSM_DATA descData = {0, 0};
    CSSM_RETURN crtn;
    CSSM_CC_HANDLE ccHand;
    CSSM_ACCESS_CREDENTIALS creds;
    CSSM_CSP_HANDLE refCspHand = CSSM_INVALID_HANDLE;
    const CSSM_KEY *cssmKey = NULL;
    uint32 keyAttr;

    memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
    memset(rawKey, 0, sizeof(CSSM_KEY));

    crtn = SecKeyGetCSSMKey(refKey, &cssmKey);
    if(crtn) {
        CSSM_PERROR("SecKeyGetCSSMKey", crtn);
        goto loser;
    }
    crtn = SecKeyGetCSPHandle(refKey, &refCspHand);
    if(crtn) {
        CSSM_PERROR("SecKeyGetCSPHandle", crtn);
        goto loser;
    }

    crtn = CSSM_CSP_CreateSymmetricContext(refCspHand,
                                           CSSM_ALGID_NONE,
                                           CSSM_ALGMODE_NONE,
                                           &creds,
                                           NULL,			// unwrappingKey
                                           NULL,			// initVector
                                           CSSM_PADDING_NONE,
                                           0,				// Params
                                           &ccHand);
    if(crtn) {
        CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn);
        return crtn;
    }

    keyAttr = rawKey->KeyHeader.KeyAttr;
    keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE |
                 CSSM_KEYATTR_MODIFIABLE);
    keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
    crtn = CSSM_WrapKey(ccHand,
                        &creds,
                        cssmKey,
                        &descData,
                        rawKey);
    if(crtn != CSSM_OK) {
        CSSM_PERROR("CSSM_WrapKey", crtn);
    }
    CSSM_DeleteContext(ccHand);

loser:
    return crtn;
}
/* 
 * Perform NULL wrap, generally expecting an error (either 
 * CSSMERR_CSP_INVALID_KEYATTR_MASK, if the raw key bits should be inaccessible,
 * or CSSMERR_CSP_INVALID_KEY_REFERENCE, if the key's header has been munged.)
 */
int nullWrapTest(
	CSSM_CSP_HANDLE	cspHand,
	CSSM_KEY_PTR	key,
	CSSM_BOOL 		quiet,
	CSSM_RETURN		expectRtn,
	const char		*keyAlgStr,
	const char 		*testStr)
{
	CSSM_CC_HANDLE				ccHand;
	CSSM_RETURN					crtn;
	CSSM_ACCESS_CREDENTIALS		creds;
	CSSM_KEY					wrappedKey;		// should not get created
	int							irtn;
	
	memset(&wrappedKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			CSSM_ALGID_NONE,
			CSSM_ALGMODE_NONE,
			&creds,				// passPhrase,
			NULL,				// wrappingKey,
			NULL,				// IV
			CSSM_PADDING_NONE,	
			0,					// Params
			&ccHand);
	if(crtn) {
		printError("cspWrapKey/CreateContext", crtn);
		return testError(quiet);
	}
	crtn = CSSM_WrapKey(ccHand,
		&creds,
		key,
		NULL,				// DescriptiveData
		&wrappedKey);
	if(crtn != expectRtn) {
		printf("***Testing %s for alg %s:\n", testStr, keyAlgStr);
		printf("   CSSM_WrapKey: expect %s\n",	cssmErrToStr(expectRtn));
		printf("   CSSM_WrapKey: got    %s\n",  cssmErrToStr(crtn));
		irtn = testError(quiet);
	}
	else {
		irtn = 0;
	}
	CSSM_DeleteContext(ccHand);
	return irtn;
}
Exemplo n.º 3
0
/* Convert a reference key to a raw key. */
static CSSM_RETURN refKeyToRaw(
	CSSM_CSP_HANDLE	cspHand,
	const CSSM_KEY	*refKey,
	CSSM_KEY_PTR	rawKey)			// RETURNED
{
	CSSM_CC_HANDLE		ccHand;
	CSSM_RETURN			crtn;
	CSSM_ACCESS_CREDENTIALS	creds;

	memset(rawKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			CSSM_ALGID_NONE,
			CSSM_ALGMODE_NONE,
			&creds,				// passPhrase
			NULL,				// wrapping key
			NULL,				// init vector
			CSSM_PADDING_NONE,	// Padding
			0,					// Params
			&ccHand);
	if(crtn) {
		sec_error("CSSM_CSP_CreateSymmetricContext: refKeyToRaw context err: %s", sec_errstr(crtn));
		return crtn;
	}

	crtn = CSSM_WrapKey(ccHand,
		&creds,
		refKey,
		NULL,			// DescriptiveData
		rawKey);
	if(crtn != CSSM_OK) {
		sec_error("CSSM_WrapKey: refKeyToRaw wrap err: %s", sec_errstr(crtn));
		return crtn;
	}
	CSSM_DeleteContext(ccHand);
	return CSSM_OK;
}
/* Convert a reference key to a raw key. */
void AppleTPSession::refKeyToRaw(
	CSSM_CSP_HANDLE	cspHand,
	const CSSM_KEY	*refKey,	
	CSSM_KEY_PTR	rawKey)			// RETURNED
{
	CSSM_CC_HANDLE		ccHand;
	CSSM_RETURN			crtn;
	CSSM_ACCESS_CREDENTIALS	creds;
	
	memset(rawKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			CSSM_ALGID_NONE,
			CSSM_ALGMODE_NONE,
			&creds,				// passPhrase
			NULL,				// wrapping key
			NULL,				// init vector
			CSSM_PADDING_NONE,	// Padding
			0,					// Params
			&ccHand);
	if(crtn) {
		tpCredDebug("AppleTPSession::refKeyToRaw: context err");
		CssmError::throwMe(crtn);
	}
	
	crtn = CSSM_WrapKey(ccHand,
		&creds,
		refKey,
		NULL,			// DescriptiveData
		rawKey);
	if(crtn != CSSM_OK) {
		tpCredDebug("AppleTPSession::refKeyToRaw: wrapKey err");
		CssmError::throwMe(crtn);
	}
	CSSM_DeleteContext(ccHand);
}
Exemplo n.º 5
0
/*
 * Cook up a symmetric encryption context for the specified key,
 * inferring all needed attributes solely from the key algorithm.
 * This is obviously not a one-size-fits all function, but rather
 * the "most common case". If you need to encrypt/decrypt with other
 * padding, mode, etc., do it yourself.
 */
static CSSM_RETURN genCryptHandle(
	CSSM_CSP_HANDLE cspHandle,
	const CSSM_KEY	*key,
	const CSSM_DATA	*ivPtr,
	CSSM_CC_HANDLE	*ccHandle)
{
	CSSM_ALGORITHMS		keyAlg = key->KeyHeader.AlgorithmId;
	CSSM_ALGORITHMS		encrAlg;
	CSSM_ENCRYPT_MODE	encrMode = CSSM_ALGMODE_NONE;
	CSSM_PADDING 		encrPad = CSSM_PADDING_NONE;
	CSSM_RETURN			crtn;
	CSSM_CC_HANDLE		ccHand = 0;
	CSSM_ACCESS_CREDENTIALS	creds;
	CSSM_BOOL			isSymmetric = CSSM_TRUE;
	
	/* 
	 * Infer algorithm - ususally it's the same as in the key itself
	 */
	switch(keyAlg) {
		case CSSM_ALGID_3DES_3KEY:
			encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
			break;
		default:
			encrAlg = keyAlg;
			break;
	}
	
	/* infer mode and padding */
	switch(encrAlg) {
		/* 8-byte block ciphers */
		case CSSM_ALGID_DES:
		case CSSM_ALGID_3DES_3KEY_EDE:
		case CSSM_ALGID_RC5:
		case CSSM_ALGID_RC2:
			encrMode = CSSM_ALGMODE_CBCPadIV8;
			encrPad = CSSM_PADDING_PKCS5;
			break;
		
		/* 16-byte block ciphers */
		case CSSM_ALGID_AES:
			encrMode = CSSM_ALGMODE_CBCPadIV8;
			encrPad = CSSM_PADDING_PKCS7;
			break;
			
		/* stream ciphers */
		case CSSM_ALGID_ASC:
		case CSSM_ALGID_RC4:
			encrMode = CSSM_ALGMODE_NONE;
			encrPad = CSSM_PADDING_NONE;
			break;
			
		/* RSA asymmetric */
		case CSSM_ALGID_RSA:
			/* encrMode not used */
			encrPad = CSSM_PADDING_PKCS1;
			isSymmetric = CSSM_FALSE;
			break;
		default:
			/* don't wing it - abort */
			return CSSMERR_CSP_INTERNAL_ERROR;
	}
	
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	if(isSymmetric) {
		crtn = CSSM_CSP_CreateSymmetricContext(cspHandle,
			encrAlg,
			encrMode,
			NULL,			// access cred
			key,
			ivPtr,			// InitVector
			encrPad,
			NULL,			// Params
			&ccHand);
	}
	else {
		crtn = CSSM_CSP_CreateAsymmetricContext(cspHandle,
			encrAlg,
			&creds,			// access
			key,
			encrPad,
			&ccHand);
	
	}
	if(crtn) {
		return crtn;
	}
	*ccHandle = ccHand;
	return CSSM_OK;
}
Exemplo n.º 6
0
/*
 * Wrap a private key, yielding shrouded key bits. 
 */
CSSM_RETURN p12WrapKey(
	CSSM_CSP_HANDLE		cspHand,
	CSSM_KEY_PTR		privKey,
	const CSSM_ACCESS_CREDENTIALS *privKeyCreds,
	CSSM_ALGORITHMS		keyAlg,				// of the unwrapping key
	CSSM_ALGORITHMS		encrAlg,
	CSSM_ALGORITHMS		pbeHashAlg,			// SHA1, MD5 only
	uint32				keySizeInBits,
	uint32				blockSizeInBytes,	// for IV
	CSSM_PADDING		padding,			// CSSM_PADDING_PKCS7, etc.
	CSSM_ENCRYPT_MODE	mode,				// CSSM_ALGMODE_CBCPadIV8, etc.
	uint32				iterCount,
	const CSSM_DATA		&salt,
	const CSSM_DATA		*pwd,		// unicode external representation
	const CSSM_KEY		*passKey,
	SecNssCoder			&coder,		// for mallocing keyBits
	CSSM_DATA			&shroudedKeyBits)	// RETURNED
{
	CSSM_RETURN crtn;
	CSSM_KEY ckey;
	CSSM_CC_HANDLE ccHand = 0;
	CSSM_KEY wrappedKey;
	CSSM_CONTEXT_ATTRIBUTE attr;
	CSSM_DATA descrData = {0, NULL};
	CSSM_ACCESS_CREDENTIALS creds;
	
	/* key must be extractable */
	if (!(privKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)) {
		return errSecDataNotAvailable;
	}

	if(privKeyCreds == NULL) {
		/* i.e., key is from the bare CSP with no ACL support */
		memset(&creds, 0, sizeof(creds));
		privKeyCreds = &creds;
	}
	
	/* P12 style IV derivation, optional */
	CSSM_DATA iv = {0, NULL};
	CSSM_DATA_PTR ivPtr = NULL;
	if(blockSizeInBytes) {
		coder.allocItem(iv, blockSizeInBytes);
		ivPtr = &iv;
	}
	
	/* P12 style key derivation */
	crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
		keySizeInBits, iterCount, salt, pwd, passKey, iv);
	if(crtn) {
		return crtn;
	}	
	/* subsequent errors to errOut: */
		
	/* CSSM context */
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
		encrAlg,
		mode,
		NULL,			// access cred
		&ckey,
		ivPtr,			// InitVector, optional
		padding,	
		NULL,			// Params
		&ccHand);
	if(crtn) {
		p12LogCssmError("CSSM_CSP_CreateSymmetricContext", crtn);
		goto errOut;
	}
	
	memset(&wrappedKey, 0, sizeof(CSSM_KEY));
	
	/* specify PKCS8 wrap format */
	attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT;
	attr.AttributeLength = sizeof(uint32);
	attr.Attribute.Uint32 = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
	crtn = CSSM_UpdateContextAttributes(
		ccHand,
		1,
		&attr);
	if(crtn) {
		p12LogCssmError("CSSM_UpdateContextAttributes", crtn);
		goto errOut;
	}
	
	crtn = CSSM_WrapKey(ccHand,
		privKeyCreds,
		privKey,
		&descrData,			// DescriptiveData
		&wrappedKey);
	if(crtn) {
		p12LogCssmError("CSSM_WrapKey", crtn);
	}
	else {
		coder.allocCopyItem(wrappedKey.KeyData, shroudedKeyBits);
		
		/* this was mallocd by CSP */
		freeCssmMemory(cspHand, wrappedKey.KeyData.Data);
	}
errOut:
	if(ccHand) {
		CSSM_DeleteContext(ccHand);
	}
	CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
	return crtn;
}
Exemplo n.º 7
0
/*
 * Unwrap a shrouded key.
 */
CSSM_RETURN p12UnwrapKey(
	CSSM_CSP_HANDLE		cspHand,
	CSSM_DL_DB_HANDLE_PTR	dlDbHand,		// optional
	int					keyIsPermanent,		// nonzero - store in DB
	const CSSM_DATA		&shroudedKeyBits,
	CSSM_ALGORITHMS		keyAlg,				// of the unwrapping key
	CSSM_ALGORITHMS		encrAlg,
	CSSM_ALGORITHMS		pbeHashAlg,			// SHA1, MD5 only
	uint32				keySizeInBits,
	uint32				blockSizeInBytes,	// for IV
	CSSM_PADDING		padding,			// CSSM_PADDING_PKCS7, etc.
	CSSM_ENCRYPT_MODE	mode,				// CSSM_ALGMODE_CBCPadIV8, etc.
	uint32				iterCount,
	const CSSM_DATA		&salt,
	const CSSM_DATA		*pwd,		// unicode external representation
	const CSSM_KEY		*passKey,
	SecNssCoder			&coder,		// for mallocing privKey
	const CSSM_DATA		&labelData,
	SecAccessRef		access,		// optional 
	bool				noAcl,
	CSSM_KEYUSE			keyUsage,
	CSSM_KEYATTR_FLAGS	keyAttrs,

	/*
	 * Result: a private key, reference format, optionaly stored
	 * in dlDbHand
	 */
	CSSM_KEY_PTR		&privKey)
{
	CSSM_RETURN crtn;
	CSSM_KEY ckey;
	CSSM_CC_HANDLE ccHand = 0;
	CSSM_KEY wrappedKey;
	CSSM_KEY unwrappedKey;
	CSSM_KEYHEADER &hdr = wrappedKey.KeyHeader;
	CSSM_DATA descrData = {0, NULL};	// not used for PKCS8 wrap 
	CSSM_KEYATTR_FLAGS reqAttr = keyAttrs;
	
	ResourceControlContext rcc;
	ResourceControlContext *rccPtr = NULL;
	Security::KeychainCore::Access::Maker maker;
	
	/* P12 style IV derivation, optional */
	CSSM_DATA iv = {0, NULL};
	CSSM_DATA_PTR ivPtr = NULL;
	if(blockSizeInBytes) {
		coder.allocItem(iv, blockSizeInBytes);
		ivPtr = &iv;
	}
	
	/* P12 style key derivation */
	crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
		keySizeInBits, iterCount, salt, pwd, passKey, iv);
	if(crtn) {
		return crtn;
	}	
	/* subsequent errors to errOut: */
		
	/* CSSM context */
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
		encrAlg,
		mode,
		NULL,			// access cred
		&ckey,
		ivPtr,			// InitVector, optional
		padding,	
		NULL,			// Params
		&ccHand);
	if(crtn) {
		p12LogCssmError("CSSM_CSP_CreateSymmetricContext", crtn);
		goto errOut;
	}
	if(dlDbHand) {
		crtn = p12AddContextAttribute(ccHand, 
			CSSM_ATTRIBUTE_DL_DB_HANDLE,
			sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE),
			dlDbHand);
		if(crtn) {
			p12LogCssmError("AddContextAttribute", crtn);
			goto errOut;
		}
	}
	
	/*
	 * Cook up minimal WrappedKey header fields
	 */
	memset(&wrappedKey, 0, sizeof(CSSM_KEY));
	memset(&unwrappedKey, 0, sizeof(CSSM_KEY));
	
	hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
	hdr.BlobType = CSSM_KEYBLOB_WRAPPED;
	hdr.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
	
	/* 
	 * This one we do not know. The CSP will figure out the format 
	 * of the unwrapped key after it decrypts the raw key material. 
	 */
	hdr.AlgorithmId = CSSM_ALGID_NONE;
	hdr.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
	
	/* also inferred by CSP */
	hdr.LogicalKeySizeInBits = 0;
	hdr.KeyAttr = CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE;
	hdr.KeyUsage = CSSM_KEYUSE_ANY;
	hdr.WrapAlgorithmId = encrAlg;
	hdr.WrapMode = mode;
	
	if(dlDbHand && keyIsPermanent) {
		reqAttr |= CSSM_KEYATTR_PERMANENT;
	}

	wrappedKey.KeyData = shroudedKeyBits;
	
	if(!noAcl) {
		// Create a Access::Maker for the initial owner of the private key.
		memset(&rcc, 0, sizeof(rcc));
		maker.initialOwner(rcc);
		rccPtr = &rcc;
	}
	
	crtn = CSSM_UnwrapKey(ccHand,
		NULL,				// PublicKey
		&wrappedKey,
		keyUsage,
		reqAttr,
		&labelData,
		rccPtr,					// CredAndAclEntry
		privKey,
		&descrData);			// required
	if(crtn) {
		p12LogCssmError("CSSM_UnwrapKey", crtn);
		if(crtn == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) {
			/* report in a keychain-friendly way */
			crtn = errSecDuplicateItem;
		}
	}
	
	// Finally fix the acl and owner of the private key to the 
	// specified access control settings.
	if((crtn == CSSM_OK) && !noAcl) {
		try {
			CssmClient::KeyAclBearer bearer(
				cspHand, *privKey, Allocator::standard());
			SecPointer<KeychainCore::Access> initialAccess(access ?
				KeychainCore::Access::required(access) :		/* caller-supplied */
				new KeychainCore::Access("privateKey"));		/* default */
			initialAccess->setAccess(bearer, maker);
		}
		catch (const CssmError &e) {
			/* not implemented means we're talking to the CSP which does
			 * not implement ACLs */
			if(e.error != CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED) {
				crtn = e.error;
			}
		}
		catch(...) {
			p12ErrorLog("p12 exception on setAccess\n");
			crtn = errSecAuthFailed;	/* ??? */
		}
	}

errOut:
	if(ccHand) {
		CSSM_DeleteContext(ccHand);
	}
	CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
	return crtn;
}
Exemplo n.º 8
0
/*
 * Decrypt (typically, an encrypted P7 ContentInfo contents)
 */
CSSM_RETURN p12Encrypt(
	CSSM_CSP_HANDLE		cspHand,
	const CSSM_DATA		&plainText,
	CSSM_ALGORITHMS		keyAlg,				
	CSSM_ALGORITHMS		encrAlg,
	CSSM_ALGORITHMS		pbeHashAlg,			// SHA1, MD5 only
	uint32				keySizeInBits,
	uint32				blockSizeInBytes,	// for IV
	CSSM_PADDING		padding,			// CSSM_PADDING_PKCS7, etc.
	CSSM_ENCRYPT_MODE	mode,				// CSSM_ALGMODE_CBCPadIV8, etc.
	uint32				iterCount,
	const CSSM_DATA		&salt,
	/* exactly one of the following two must be valid */
	const CSSM_DATA		*pwd,		// unicode external representation
	const CSSM_KEY		*passKey,
	SecNssCoder			&coder,		// for mallocing cipherText
	CSSM_DATA			&cipherText)
{
	CSSM_RETURN crtn;
	CSSM_KEY ckey;
	CSSM_CC_HANDLE ccHand = 0;
	CSSM_DATA ourCtext = {0, NULL};
	CSSM_DATA remData = {0, NULL};
	
	/* P12 style IV derivation, optional */
	CSSM_DATA iv = {0, NULL};
	CSSM_DATA_PTR ivPtr = NULL;
	if(blockSizeInBytes) {
		coder.allocItem(iv, blockSizeInBytes);
		ivPtr = &iv;
	}
	
	/* P12 style key derivation */
	crtn = p12KeyGen(cspHand, ckey, true, keyAlg, pbeHashAlg,
		keySizeInBits, iterCount, salt, pwd, passKey, iv);
	if(crtn) {
		return crtn;
	}	
	/* subsequent errors to errOut: */
		
	/* CSSM context */
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
		encrAlg,
		mode,
		NULL,			// access cred
		&ckey,
		ivPtr,			// InitVector, optional
		padding,	
		NULL,			// Params
		&ccHand);
	if(crtn) {
		cuPrintError("CSSM_CSP_CreateSymmetricContext", crtn);
		goto errOut;
	}
	
	/* go - CSP mallocs ctext and rem data */
	CSSM_SIZE bytesEncrypted;
	crtn = CSSM_EncryptData(ccHand,
		&plainText,
		1,
		&ourCtext,
		1,
		&bytesEncrypted,
		&remData);
	if(crtn) {
		cuPrintError("CSSM_DecryptData", crtn);
	}
	else {
		coder.allocCopyItem(ourCtext, cipherText);
		cipherText.Length = bytesEncrypted;
		
		/* plaintext copied into coder space; free the memory allocated
		 * by the CSP */
		freeCssmMemory(cspHand, ourCtext.Data);
	}
	/* an artifact of CSPFUllPLuginSession - this never contains
	 * valid data but sometimes gets mallocds */
	if(remData.Data) {
		freeCssmMemory(cspHand, remData.Data);
	}
errOut:
	if(ccHand) {
		CSSM_DeleteContext(ccHand);
	}
	CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
	return crtn;
}
/* NULL wrap a key to specified format. */
static CSSM_RETURN nullWrapKey(CSSM_CSP_HANDLE cspHand,
	const CSSM_KEY			*refKey,	
	CSSM_KEYBLOB_FORMAT		blobFormat,
	CSSM_KEY_PTR			rawKey)			// RETURNED
{
	CSSM_CC_HANDLE		ccHand;
	CSSM_RETURN			crtn;
	CSSM_ACCESS_CREDENTIALS	creds;
	CSSM_DATA descData = {0, 0};
	
	memset(rawKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
				CSSM_ALGID_NONE,
				CSSM_ALGMODE_NONE,
				&creds,			// passPhrase
				NULL,			// unwrappingKey
				NULL,			// initVector
				CSSM_PADDING_NONE,
				0,				// Params
				&ccHand);
	if(crtn) {
		printError("cspWrapKey/CreateContext", crtn);
		return crtn;
	}
	if(blobFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) {
		/* only add this attribute if it's not the default */
		CSSM_ATTRIBUTE_TYPE attrType;
	
		switch(refKey->KeyHeader.KeyClass) {
			case CSSM_KEYCLASS_SESSION_KEY:
				attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT;
				break;
			case CSSM_KEYCLASS_PUBLIC_KEY:
				attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT;
				break;
			case CSSM_KEYCLASS_PRIVATE_KEY:
				attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT;
				break;
			default:
				printf("***Bogus KeyClass in nullWrapKey\n");
				return -1;
		}
		CSSM_CONTEXT_ATTRIBUTE attr;
		attr.AttributeType = attrType;
		attr.AttributeLength = sizeof(uint32);
		attr.Attribute.Uint32 = blobFormat;
		crtn = CSSM_UpdateContextAttributes(
			ccHand,
			1,
			&attr);
		if(crtn) {
			printError("CSSM_UpdateContextAttributes", crtn);
			return crtn;
		}
	}
	crtn = CSSM_WrapKey(ccHand,
		&creds,
		refKey,
		&descData,	
		rawKey);
	if(crtn != CSSM_OK) {
		printError("CSSM_WrapKey", crtn);
	}
	if(CSSM_DeleteContext(ccHand)) {
		printf("CSSM_DeleteContext failure\n");
	}
	return crtn;
}
Exemplo n.º 10
0
static SecCmsCipherContext *
SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid, PRBool encrypt)
{
    SecCmsCipherContext *cc;
    CSSM_CC_HANDLE ciphercc = 0;
    SECOidData *oidData;
    SECOidTag algtag;
    CSSM_ALGORITHMS algorithm;
    CSSM_PADDING padding = CSSM_PADDING_PKCS7;
    CSSM_ENCRYPT_MODE mode;
    CSSM_CSP_HANDLE cspHandle;
    const CSSM_KEY *cssmKey;
    OSStatus rv;
    uint8 ivbuf[8];
    CSSM_DATA initVector = { sizeof(ivbuf), ivbuf };
    //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(CSSM_DATA_PTR) };

    rv = SecKeyGetCSPHandle(key, &cspHandle);
    if (rv)
	goto loser;
    rv = SecKeyGetCSSMKey(key, &cssmKey);
    if (rv)
	goto loser;

    // @@@ Add support for PBE based stuff

    oidData = SECOID_FindOID(&algid->algorithm);
    if (!oidData)
	goto loser;
    algtag = oidData->offset;
    algorithm = oidData->cssmAlgorithm;
    if (!algorithm)
	goto loser;

    switch (algtag)
    {
    case SEC_OID_RC2_CBC:
    case SEC_OID_RC4:
    case SEC_OID_DES_EDE3_CBC:
    case SEC_OID_DES_EDE:
    case SEC_OID_DES_CBC:
    case SEC_OID_RC5_CBC_PAD:
    case SEC_OID_AES_128_CBC:
    case SEC_OID_AES_192_CBC:
    case SEC_OID_AES_256_CBC:
    case SEC_OID_FORTEZZA_SKIPJACK:
	mode = CSSM_ALGMODE_CBCPadIV8;
	break;

    case SEC_OID_DES_ECB:
    case SEC_OID_AES_128_ECB:
    case SEC_OID_AES_192_ECB:
    case SEC_OID_AES_256_ECB:
	mode = CSSM_ALGMODE_ECBPad;
	break;

    case SEC_OID_DES_OFB:
	mode = CSSM_ALGMODE_OFBPadIV8;
	break;

    case SEC_OID_DES_CFB:
	mode = CSSM_ALGMODE_CFBPadIV8;
	break;

    default:
	goto loser;
    }

    if (encrypt)
    {
	CSSM_CC_HANDLE randomcc;
	//SECItem *parameters;

	// Generate random initVector
	if (CSSM_CSP_CreateRandomGenContext(cspHandle,
		CSSM_ALGID_APPLE_YARROW,
		NULL, /* seed*/
		initVector.Length,
		&randomcc))
	    goto loser;

	if (CSSM_GenerateRandom(randomcc, &initVector))
	    goto loser;
	CSSM_DeleteContext(randomcc);

	// Put IV into algid.parameters
	switch (algtag)
	{
	case SEC_OID_RC4:
	case SEC_OID_DES_EDE3_CBC:
	case SEC_OID_DES_EDE:
	case SEC_OID_DES_CBC:
	case SEC_OID_AES_128_CBC:
	case SEC_OID_AES_192_CBC:
	case SEC_OID_AES_256_CBC:
	case SEC_OID_FORTEZZA_SKIPJACK:
	case SEC_OID_DES_ECB:
	case SEC_OID_AES_128_ECB:
	case SEC_OID_AES_192_ECB:
	case SEC_OID_AES_256_ECB:
	case SEC_OID_DES_OFB:
	case SEC_OID_DES_CFB:
	    /* Just encode the initVector as an octet string. */
	    if (!SEC_ASN1EncodeItem(poolp, &algid->parameters,
				    &initVector, SEC_OctetStringTemplate))
		goto loser;
	    break;
    
	case SEC_OID_RC2_CBC:
	{
	    sec_rc2cbcParameter rc2 = {};
	    unsigned long rc2version;
	    SECItem *newParams;

	    rc2.iv = initVector;
	    rc2version = rc2_unmap(cssmKey->KeyHeader.LogicalKeySizeInBits);
	    if (!SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion),
					       rc2version))
		goto loser;
	    newParams = SEC_ASN1EncodeItem (poolp, &algid->parameters, &rc2,
				sec_rc2cbc_parameter_template);
	    PORT_Free(rc2.rc2ParameterVersion.Data);
	    if (newParams == NULL)
		goto loser;
	    break;
	}
	case SEC_OID_RC5_CBC_PAD:
	default:
	    // @@@ Implement rc5 params stuff.
	    goto loser;
	    break;
	}
    }
    else
    {
	// Extract IV from algid.parameters
	// Put IV into algid.parameters
	switch (algtag)
	{
	case SEC_OID_RC4:
	case SEC_OID_DES_EDE3_CBC:
	case SEC_OID_DES_EDE:
	case SEC_OID_DES_CBC:
	case SEC_OID_AES_128_CBC:
	case SEC_OID_AES_192_CBC:
	case SEC_OID_AES_256_CBC:
	case SEC_OID_FORTEZZA_SKIPJACK:
	case SEC_OID_DES_ECB:
	case SEC_OID_AES_128_ECB:
	case SEC_OID_AES_192_ECB:
	case SEC_OID_AES_256_ECB:
	case SEC_OID_DES_OFB:
	case SEC_OID_DES_CFB:
	{
	    CSSM_DATA iv = {};
	    /* Just decode the initVector from an octet string. */
	    rv = SEC_ASN1DecodeItem(NULL, &iv, SEC_OctetStringTemplate, &(algid->parameters));
	    if (rv)
		goto loser;
	    if (initVector.Length != iv.Length) {
		PORT_Free(iv.Data);
		goto loser;
	    }
	    memcpy(initVector.Data, iv.Data, initVector.Length);
	    PORT_Free(iv.Data);
	    break;
	}
	case SEC_OID_RC2_CBC:
	{
	    sec_rc2cbcParameter rc2 = {};
	    unsigned long ulEffectiveBits;

	    rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2cbc_parameter_template,
							    &(algid->parameters));
	    if (rv)
		goto loser;

	    if (initVector.Length != rc2.iv.Length) {
		PORT_Free(rc2.iv.Data);
		PORT_Free(rc2.rc2ParameterVersion.Data);
		goto loser;
	    }
	    memcpy(initVector.Data, rc2.iv.Data, initVector.Length);
	    PORT_Free(rc2.iv.Data);

	    ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion);
	    PORT_Free(rc2.rc2ParameterVersion.Data);
	    if (ulEffectiveBits != cssmKey->KeyHeader.LogicalKeySizeInBits)
		goto loser;
	    break;
	}
	case SEC_OID_RC5_CBC_PAD:
	default:
	    // @@@ Implement rc5 params stuff.
	    goto loser;
	    break;
	}
    }

    if (CSSM_CSP_CreateSymmetricContext(cspHandle,
	    algorithm,
	    mode,
	    NULL, /* accessCred */
	    cssmKey,
	    &initVector,
	    padding,
	    NULL, /* reserved */
	    &ciphercc))
	goto loser;

    if (encrypt)
	rv = CSSM_EncryptDataInit(ciphercc);
    else
	rv = CSSM_DecryptDataInit(ciphercc);
    if (rv)
	goto loser;

    cc = (SecCmsCipherContext *)PORT_ZAlloc(sizeof(SecCmsCipherContext));
    if (cc == NULL)
	goto loser;

    cc->cc = ciphercc;
    cc->encrypt = encrypt;

    return cc;
loser:
    if (ciphercc)
	CSSM_DeleteContext(ciphercc);

    return NULL;
}
Exemplo n.º 11
0
/* wrap key function. */
static CSSM_RETURN wrapKey(CSSM_CSP_HANDLE cspHand,
	const CSSM_KEY_PTR		unwrappedKey,		// must be ref
	const CSSM_KEY_PTR		wrappingKey,
	CSSM_ALGORITHMS			wrapAlg,
	CSSM_ENCRYPT_MODE		wrapMode,
	CSSM_KEYBLOB_FORMAT		wrapFormat,			// NONE, PKCS7, PKCS8
	CSSM_PADDING 			wrapPad,
	CSSM_KEY_PTR			wrappedKey)			// RETURNED
{
	CSSM_CC_HANDLE		ccHand;
	CSSM_RETURN			crtn;
	CSSM_RETURN			crtn2;
	#if	WRAP_KEY_REQUIRES_CREDS
	CSSM_ACCESS_CREDENTIALS	creds;
	#endif
	
	#if 0
	if(unwrappedKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
		printf("Hey! you can only wrap a reference key!\n");
		return CSSM_ERRCODE_INTERNAL_ERROR;
	}
	#endif
	memset(wrappedKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	/* special case for NULL wrap - no wrapping key */
	if((wrappingKey == NULL) ||
	   (wrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) {
		crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
				wrapAlg,
				wrapMode,
				&creds,					// accessCred
				wrappingKey,
				&initVector,
				wrapPad,				// Padding
				NULL,					// Reserved
				&ccHand);
		if(crtn) {
			printError("cspWrapKey/CreateContext", crtn);
			return CSSM_ERRCODE_INTERNAL_ERROR;
		}
	}
	else {
		crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
				wrapAlg,
				&creds,			// passPhrase
				wrappingKey,
				wrapPad,		// Padding
				&ccHand);
		if(crtn) {
			printError("cspWrapKey/CreateContext", crtn);
			return CSSM_ERRCODE_INTERNAL_ERROR;
		}
		/* CMS requires 8-byte IV */
		crtn = AddContextAttribute(ccHand,
			CSSM_ATTRIBUTE_INIT_VECTOR,
			sizeof(CSSM_DATA),
			CAT_Ptr,
			&initVector,
			0);
		if(crtn) {
			printError("CSSM_UpdateContextAttributes", crtn);
			return crtn;
		}
	}
	if(wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) {
		/* only add this attribute if it's not the default */
		CSSM_CONTEXT_ATTRIBUTE attr;
		attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT;
		attr.AttributeLength = sizeof(uint32);
		attr.Attribute.Uint32 = wrapFormat;
		crtn = CSSM_UpdateContextAttributes(
			ccHand,
			1,
			&attr);
		if(crtn) {
			printError("CSSM_UpdateContextAttributes", crtn);
			return crtn;
		}
	}
	crtn = CSSM_WrapKey(ccHand,
		#if	WRAP_KEY_REQUIRES_CREDS
		&creds,
		#else
		NULL,			// AccessCred
		#endif
		unwrappedKey,
		NULL,			// DescriptiveData
		wrappedKey);
	if(crtn != CSSM_OK) {
		printError("CSSM_WrapKey", crtn);
	}
	if((crtn2 = CSSM_DeleteContext(ccHand))) {
		printError("CSSM_DeleteContext", crtn2);
	}
	return crtn;
}
Exemplo n.º 12
0
/* unwrap key function. */
static CSSM_RETURN unwrapKey(CSSM_CSP_HANDLE cspHand,
	const CSSM_KEY_PTR		wrappedKey,
	const CSSM_KEY_PTR		unwrappingKey,
	CSSM_ALGORITHMS			unwrapAlg,
	CSSM_ENCRYPT_MODE		unwrapMode,
	CSSM_PADDING 			unwrapPad,
	CSSM_KEY_PTR			unwrappedKey,		// RETURNED
	const unsigned char 	*keyLabel,
	unsigned 				keyLabelLen)
{
	CSSM_CC_HANDLE		ccHand;
	CSSM_RETURN			crtn;
	CSSM_RETURN			crtn2;
	CSSM_DATA			labelData;
	uint32				keyAttr;
	CSSM_DATA			descData = { 0, NULL };
	CSSM_ACCESS_CREDENTIALS	creds;
	 
	memset(unwrappedKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	if((unwrappingKey == NULL) ||
	   (unwrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) {
		crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
				unwrapAlg,
				unwrapMode,
				&creds,				// accessCreds
				unwrappingKey,
				&initVector,	
				unwrapPad,			// Padding
				0,					// Reserved
				&ccHand);
		if(crtn) {
			printError("cspUnwrapKey/CreateContext", crtn);
			return CSSM_ERRCODE_INTERNAL_ERROR;
		}
	}
	else {
		crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
				unwrapAlg,
				&creds,			// passPhrase,
				unwrappingKey,
				unwrapPad,		// Padding
				&ccHand);
		if(crtn) {
			printError("cspUnwrapKey/CreateContext", crtn);
			return CSSM_ERRCODE_INTERNAL_ERROR;
		}
		/* CMS requires 8-byte IV */
		crtn = AddContextAttribute(ccHand,
			CSSM_ATTRIBUTE_INIT_VECTOR,
			sizeof(CSSM_DATA),
			CAT_Ptr,
			&initVector,
			0);
		if(crtn) {
			printError("CSSM_UpdateContextAttributes", crtn);
			return crtn;
		}
	}
	labelData.Data = (uint8 *)keyLabel;
	labelData.Length = keyLabelLen;
	
	/*
	 * New keyAttr - clear some old bits, make sure we ask for ref key
	 */
	keyAttr = wrappedKey->KeyHeader.KeyAttr;
	keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE);
	keyAttr |= CSSM_KEYATTR_RETURN_REF;
	crtn = CSSM_UnwrapKey(ccHand,
		NULL,		// PublicKey
		wrappedKey,
		CSSM_KEYUSE_ANY,		// FIXME
		keyAttr,
		&labelData,
		NULL,					// CredAndAclEntry
		unwrappedKey,
		&descData);				// required 
	if(crtn != CSSM_OK) {
		printError("CSSM_UnwrapKey", crtn);
	}
	if((crtn2 = CSSM_DeleteContext(ccHand))) {
		printError("CSSM_DeleteContext", crtn2);
	}
	return crtn;
}
static int doDecrypt(
	CSSM_CSP_HANDLE	cspHand,
	const char *algStr,
	CSSM_KEY_PTR key,			// session, private
	CSSM_ALGORITHMS encrAlg,
	CSSM_ENCRYPT_MODE encrMode,
	CSSM_PADDING encrPad,
	DecrResult expResult,
	CSSM_BOOL quiet)
{
	uint8 ctextData[CTEXT_SIZE];
	CSSM_DATA ctext = {CTEXT_SIZE, ctextData};
	uint8 someIvData[IV_SIZE];
	CSSM_DATA someIv = {IV_SIZE, someIvData};
	 
	 /*
	  * I have not found a way to guarantee decrypt failure here, no matter
	  * what ctext and IV I specify. We can't just do an encrypt and 
	  * munge because we might be testing a bad (expired) key. 
	  * We might have to redesign, first generating a good key, then an
	  * expired key from it...? Until then this test is loose about
	  * handling "key is good" detection.
	  */
	memset(ctextData, 0, CTEXT_SIZE);	// guaranteed bad padding
	memset(someIvData, 0, IV_SIZE);
	
	CSSM_CC_HANDLE cryptHand = 0;
	CSSM_RETURN crtn;
	CSSM_ACCESS_CREDENTIALS	creds;
	
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	
	if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY) {
		crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			encrAlg,
			encrMode,
			NULL,			// access cred
			key,
			&someIv,
			encrPad,	
			NULL,			// Params
			&cryptHand);
		if(crtn) {
			printError("CSSM_CSP_CreateSymmetricContext", crtn);
			return testError(quiet);
		}
	}
	else if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) {
		crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
			encrAlg,
			&creds,			// access
			key,
			encrPad,
			&cryptHand);
		if(crtn) {
			printError("CSSM_CSP_CreateAsymmetricContext", crtn);
			return testError(quiet);
		}
	}
	else {
		printf("***BRRZAP! Only decrypt with session and private"
			" keys\n");
		exit(1);
	}

	CSSM_DATA ptext = {0, NULL};
	CSSM_DATA remData = {0, NULL};
	CSSM_SIZE bDecr;
	int irtn = 0;
	
	crtn = CSSM_DecryptData(cryptHand,
		&ctext,
		1,
		&ptext,
		1,
		&bDecr,
		&remData);
	switch(expResult) {
		case DR_BadStartDate:
			if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE) {
				printf("***Decrypt with %s: expected INVALID_KEY_START_DATE, "
					"got %s.\n", algStr, cssmErrToStr(crtn));
				irtn = testError(quiet);
			}
			break;
		case DR_BadEndDate:
			if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE) {
				printf("***Decrypt with %s: expected INVALID_KEY_END_DATE, "
					"got %s.\n", algStr, cssmErrToStr(crtn));
				irtn = testError(quiet);
			}
			break;
		case DR_BadData:
			switch(crtn) {
				case CSSM_OK:						// good data, seen sometimes
				case CSSMERR_CSP_INVALID_DATA:		// common case
				case CSSMERR_CSP_INTERNAL_ERROR:	// default case in CSP's
													//   throwRsaDsa() :-(
					break;
				default:
					printf("***Decrypt with %s: expected INVALID_DATA or OK, "
						"got %s.\n",
						algStr, cssmErrToStr(crtn));
					irtn = testError(quiet);
					break;
			}
			break;
	}
	appFreeCssmData(&ptext, CSSM_FALSE);
	appFreeCssmData(&remData, CSSM_FALSE);
	CSSM_DeleteContext(cryptHand);
	return irtn;
}
static int doEncrypt(
	CSSM_CSP_HANDLE	cspHand,
	const char *algStr,
	CSSM_KEY_PTR key,			// session, public
	CSSM_ALGORITHMS encrAlg,
	CSSM_ENCRYPT_MODE encrMode,
	CSSM_PADDING encrPad,
	CSSM_RETURN expRtn,			// expected result
	CSSM_BOOL quiet)
{
	uint8 ptextData[PTEXT_SIZE];
	CSSM_DATA ptext = {PTEXT_SIZE, ptextData};
	uint8 someIvData[IV_SIZE];
	CSSM_DATA someIv = {IV_SIZE, someIvData};
	 
	simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE);
	simpleGenData(&someIv, IV_SIZE, IV_SIZE);
	
	CSSM_CC_HANDLE cryptHand = 0;
	CSSM_RETURN crtn;
	CSSM_ACCESS_CREDENTIALS	creds;
	
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	
	if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY) {
		crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			encrAlg,
			encrMode,
			NULL,			// access cred
			key,
			&someIv,
			encrPad,	
			NULL,			// Params
			&cryptHand);
		if(crtn) {
			printError("CSSM_CSP_CreateSymmetricContext", crtn);
			return testError(quiet);
		}
	}
	else if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_PUBLIC_KEY) {
		crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
			encrAlg,
			&creds,			// access
			key,
			encrPad,
			&cryptHand);
		if(crtn) {
			printError("CSSM_CSP_CreateAsymmetricContext", crtn);
			return testError(quiet);
		}
	}
	else {
		printf("***BRRZAP! Only encrypt with session and public keys\n");
		exit(1);
	}

	CSSM_DATA ctext = {0, NULL};
	CSSM_DATA remData = {0, NULL};
	CSSM_SIZE bEncr;
	int irtn = 0;
	
	crtn = CSSM_EncryptData(cryptHand,
		&ptext,
		1,
		&ctext,
		1,
		&bEncr,
		&remData);
	if(crtn != expRtn) {
		if(expRtn == CSSM_OK) {
			printError("CSSM_EncryptData", crtn);
			printf("Unexpected error encrypting with %s\n", algStr);
		}
		else {
			printf("***Encrypt with %s: expected %s, got %s.\n",
				algStr, cssmErrToStr(expRtn),
				cssmErrToStr(crtn));
		}
		irtn = testError(quiet);
	}
	appFreeCssmData(&ctext, CSSM_FALSE);
	appFreeCssmData(&remData, CSSM_FALSE);
	CSSM_DeleteContext(cryptHand);
	return irtn;
}
Exemplo n.º 15
0
static int badWrapTest(
	CSSM_CSP_HANDLE		cspHand,
	CSSM_KEY_PTR		unwrappedKey,
	CSSM_KEYBLOB_FORMAT	wrapForm,
	CSSM_BOOL 			quiet,
	const char			*keyAlgStr,
	const char			*testStr)
{
	CSSM_CC_HANDLE				ccHand;
	CSSM_RETURN					crtn;
	CSSM_ACCESS_CREDENTIALS		creds;
	CSSM_KEY					wrappedKey;		// should not get created
	CSSM_KEY					wrappingKey;
	int							irtn;
		
	/* first generate a DES wrapping key */
	if(genSymKey(cspHand, &wrappingKey, CSSM_ALGID_DES, "DES", 
			CSP_DES_KEY_SIZE_DEFAULT, 
			CSSM_KEYATTR_RETURN_REF,
			CSSM_KEYUSE_ANY, CSSM_OK, quiet, 
			CSSM_FALSE, "not a test case")) {
		return 1;
	}

	memset(&wrappedKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	
	/* symmetric wrapping context */
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			CSSM_ALGID_DES,
			CSSM_ALGMODE_CBCPadIV8,
			&creds,				// passPhrase,
			&wrappingKey,	
			NULL,				// IV
			CSSM_PADDING_PKCS5,	
			0,					// Params
			&ccHand);
	if(crtn) {
		printError("cspWrapKey/CreateContext", crtn);
		return testError(quiet);
	}
	
	/* do it, demand error */
	crtn = CSSM_WrapKey(ccHand,
		&creds,
		unwrappedKey,
		NULL,				// DescriptiveData
		&wrappedKey);
	if(crtn != CSSMERR_CSP_INVALID_KEYATTR_MASK) {
		printf("***Testing %s for alg %s:\n", testStr, keyAlgStr);
		printf("   CSSM_WrapKey: expect CSSMERR_CSP_INVALID_KEYATTR_MASK, got %s\n",
			cssmErrToStr(crtn));
		irtn = testError(quiet);
	}
	else {
		irtn = 0;
	}
	CSSM_DeleteContext(ccHand);
	cspFreeKey(cspHand, &wrappingKey);
	return irtn;
}