p12GetPassKey.cpp   [plain text]


/*
 * p12GetPassKey.h - get a CSSM_ALGID_SECURE_PASSPHRASE key for encode/decode
 */

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include "p12GetPassKey.h"
#include <CoreServices.framework/Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <Security/cssmapple.h>
#include <utilLib/cspwrap.h>

/* when true, simulate secure passphrase in CSPDL */
#define SIMULATE_PASSPHRASE		1

/* 
 * Safe gets().
 * -- guaranteed no buffer overflow
 * -- guaranteed NULL-terminated string
 * -- handles empty string (i.e., response is just CR) properly
 */
void getString(
	char *buf,
	unsigned bufSize)
{
	unsigned dex;
	char c;
	char *cp = buf;
	
	for(dex=0; dex<bufSize-1; dex++) {
		c = getchar();
		if (c == EOF) {
			break;
		}
		
		if(!isprint(c)) {
			break;
		}
		switch(c) {
			case '\n':
			case '\r':
				goto done;
			default:
				*cp++ = c;
		}
	}
done:
	*cp = '\0';
}

OSStatus p12GetPassKey(
	CSSM_CSP_HANDLE	cspHand,
	GPK_Type 		gpkType,
	bool			isRawCsp,
	CSSM_KEY		*passKey)		// RETURNED
{
	if(isRawCsp || SIMULATE_PASSPHRASE) {
		char passphrase[512];
		
		if(gpkType == GPK_Decode) {
			printf("Enter passphrase for PKCS12 Decode: ");
		}
		else {
			printf("Enter passphrase for PKCS12 Encode: ");
		}
		getString(passphrase, 512);
		
		/* cook up a raw key with passphrase as data */
		unsigned phraseLen = strlen(passphrase);
		CSSM_KEY		rawKey;
		memset(&rawKey, 0, sizeof(CSSM_KEY));
		CSSM_KEYHEADER	&hdr = rawKey.KeyHeader;
		hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
		hdr.BlobType = CSSM_KEYBLOB_RAW;
		hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
		hdr.AlgorithmId = CSSM_ALGID_SECURE_PASSPHRASE;
		hdr.KeyClass = CSSM_KEYCLASS_SESSION_KEY;
		hdr.LogicalKeySizeInBits = phraseLen * 2 * 8;
		hdr.KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE;
		hdr.KeyUsage = CSSM_KEYUSE_DERIVE;
		
		#if 0
		/* data = Unicode version of C string passphrase, bigendian */
		rawKey.KeyData.Length = phraseLen * 2;
		rawKey.KeyData.Data = (uint8 *)malloc(phraseLen * 2);
		const char *cpIn = passphrase;
		char *cpOut = (char *)rawKey.KeyData.Data;
		
		for(unsigned dex=0; dex<phraseLen; dex++) {
			*cpOut++ = 0;
			*cpOut++ = *cpIn++;
		}
		#else
		
		/* data = external representation of CFString */
		CFStringRef cfStr = CFStringCreateWithCString(NULL, passphrase,
			kCFStringEncodingASCII);
		CFDataRef cfData = CFStringCreateExternalRepresentation(NULL,
			cfStr, kCFStringEncodingUnicode, 0);
		unsigned keyLen = CFDataGetLength(cfData);
		rawKey.KeyData.Length = keyLen;
		rawKey.KeyData.Data = (uint8 *)malloc(keyLen);
		memmove(rawKey.KeyData.Data, CFDataGetBytePtr(cfData), keyLen);
		CFRelease(cfData);
		CFRelease(cfStr);
		hdr.LogicalKeySizeInBits = keyLen * 8;
		#endif
		CSSM_DATA descrData = {0, NULL};
		
		/* NULL unwrap to make a ref key */
		CSSM_RETURN crtn = cspUnwrapKey(cspHand,
			&rawKey,
			NULL,			// wrappingKey
			CSSM_ALGID_NONE,
			0, 0, 0, 		// mode, pad, vector
			passKey,
			&descrData,
			"someLabel",
			9);				// labelLen 
		if(crtn) {
			printf("***Error doing NULL wrap of passKey.\n");
			return crtn;
		}
		return crtn;
	}
	else {
		printf("SS does not support secure passphrase yet.");
		/*
		 * TBD: do a DeriveKey
		 */
		return unimpErr;
	}
}