/*
 * Parse an encoded NSS_P12_AuthenticatedSafe
 */
static int authSafeParse(
	const CSSM_DATA authSafeBlob,
	P12ParseInfo &pinfo,
	unsigned depth)		// print indent depth
{
	NSS_P12_AuthenticatedSafe authSafe;
	
	memset(&authSafe, 0, sizeof(authSafe));
	if(pinfo.mCoder.decodeItem(authSafeBlob,
			NSS_P12_AuthenticatedSafeTemplate,
			&authSafe)) {
		printf("***Error decoding authSafe\n");
		return 1;
	}
	unsigned numInfos = nssArraySize((const void **)authSafe.info);
	doIndent(depth);
	printf("authSafe numInfos %u\n", numInfos);
	
	int rtn = 0;
	for(unsigned dex=0; dex<numInfos; dex++) {
		NSS_P7_DecodedContentInfo *info = authSafe.info[dex];
		doIndent(depth);
		printf("AuthSafe.info[%u] {\n", dex);
		rtn = authSafeElementParse(info, pinfo, depth+3);
		if(rtn) {
			break;
		}
		doIndent(depth);
		printf("}\n");
	}
	return rtn;
}
/* print a CFData as an X509 Name (i.e., subject or issuer) */
void printCfName(
	CFDataRef nameData,
	OidParser &parser)
{
	SecAsn1CoderRef coder = NULL;
	OSStatus ortn;

	ortn = SecAsn1CoderCreate(&coder);
	if(ortn) {
		cssmPerror("SecAsn1CoderCreate", ortn);
		return;
	}
	/* subsequent errors to errOut: */

	NSS_Name nssName = {NULL};
	unsigned numRdns;

	ortn = SecAsn1Decode(coder, 
		CFDataGetBytePtr(nameData), CFDataGetLength(nameData),
		kSecAsn1NameTemplate,
		&nssName);
	if(ortn) {
		printf("***Error decoding NSS_Name\n");
		goto errOut;
	}	
	numRdns = nssArraySize((const void **)nssName.rdns);
	for(unsigned dex=0; dex<numRdns; dex++) {
		printRdn(nssName.rdns[dex], parser);
	}

errOut:
	if(coder) {
		SecAsn1CoderRelease(coder);
	}
}
Esempio n. 3
0
/*
 * Parse an encoded NSS_P12_SafeContents. This could be either 
 * present as plaintext in an AuthSafe or decrypted. 
 */
static int safeContentsParse(pkcs12_context * context, const SecAsn1Item *contentsBlob)
{
	p12DecodeLog("safeContentsParse");

	NSS_P12_SafeContents sc;
	memset(&sc, 0, sizeof(sc));
	require_noerr(decode_item(context, contentsBlob, NSS_P12_SafeContentsTemplate,
			&sc), out);

	unsigned numBags = nssArraySize((const void **)sc.bags);
    unsigned int dex;
	for(dex=0; dex<numBags; dex++) {
		NSS_P12_SafeBag *bag = sc.bags[dex];
		assert(bag != NULL);
		
		/* ensure that *something* is there */
		require(bag->bagValue.keyBag != NULL, out);
		
		/*
		 * Break out to individual bag type
		 */
		switch(bag->type) {
			case BT_ShroudedKeyBag:
				require_noerr(shroudedKeyBagParse(context, bag), out);
				break;
			case BT_CertBag:
				require_noerr(certBagParse(context, bag), out);
				break;

			case BT_KeyBag:
				/* keyBagParse(bag); */
                p12DecodeLog("Unhandled BT_KeyBag");
				break;
			case BT_CrlBag:
				/* crlBagParse(bag); */
                p12DecodeLog("Unhandled BT_CrlBag");
				break;
			case BT_SecretBag:
				/* secretBagParse(bag); */
                p12DecodeLog("Unhandled BT_SecretBag");
				break;
			case BT_SafeContentsBag:
				/* safeContentsBagParse(bag); */
                p12DecodeLog("Unhandled BT_SafeContentsBag");
				break;
			default:
                p12DecodeLog("Unknown bag type");
                goto out;
                break;
		}
	}
    return 0;
out:
    return -1;
}
/*
 * Parse an encoded NSS_P12_SafeContents. This could be either 
 * present as plaintext in an AuthSafe or decrypted. 
 */
void P12Coder::safeContentsParse(
	const CSSM_DATA &contentsBlob,
	SecNssCoder &localCdr)
{
	p12DecodeLog("safeContentsParse");

	NSS_P12_SafeContents sc;
	memset(&sc, 0, sizeof(sc));
	if(localCdr.decodeItem(contentsBlob, NSS_P12_SafeContentsTemplate,
			&sc)) {
		p12ErrorLog("Error decoding SafeContents\n");
		P12_THROW_DECODE;
	}
	unsigned numBags = nssArraySize((const void **)sc.bags);
	for(unsigned dex=0; dex<numBags; dex++) {
		NSS_P12_SafeBag *bag = sc.bags[dex];
		assert(bag != NULL);
		
		/* ensure that *something* is there */
		if(bag->bagValue.keyBag == NULL) {
			p12ErrorLog("safeContentsParse: Empty SafeBag\n");
			P12_THROW_DECODE;
		}
		
		/*
		 * Break out to individual bag type
		 */
		switch(bag->type) {
			case BT_KeyBag:
				keyBagParse(*bag, localCdr);
				break;
			case BT_ShroudedKeyBag:
				shroudedKeyBagParse(*bag, localCdr);
				break;
			case BT_CertBag:
				certBagParse(*bag, localCdr);
				break;
			case BT_CrlBag:
				crlBagParse(*bag, localCdr);
				break;
			case BT_SecretBag:
				secretBagParse(*bag ,localCdr);
				break;
			case BT_SafeContentsBag:
				safeContentsBagParse(*bag, localCdr);
				break;
			default:
				p12ErrorLog("unknown  p12 BagType (%u)\n",
					(unsigned)bag->type);
				P12_THROW_DECODE;
		}
	}
}
static void printRdn(const NSS_RDN *rdn, OidParser &parser)
{
	unsigned numAtvs = nssArraySize((const void **)rdn->atvs);
	char						*fieldName;

	for(unsigned dex=0; dex<numAtvs; dex++) {
		const NSS_ATV *atv = rdn->atvs[dex];
		if(compareOids(&atv->type, &CSSMOID_CountryName)) {
			fieldName = "Country       ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_OrganizationName)) {
			fieldName = "Org           ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_LocalityName)) {
			fieldName = "Locality      ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_OrganizationalUnitName)) {
			fieldName = "OrgUnit       ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_CommonName)) {
			fieldName = "Common Name   ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_Surname)) {
			fieldName = "Surname       ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_Title)) {
			fieldName = "Title         ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_Surname)) {
			fieldName = "Surname       ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_StateProvinceName)) {
			fieldName = "State         ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_CollectiveStateProvinceName)) {
			fieldName = "Coll. State   ";      
		}
		else if(compareOids(&atv->type, &CSSMOID_EmailAddress)) {
			/* deprecated, used by Thawte */
			fieldName = "Email addrs   ";      
		}
		else {
			fieldName = "Other name    ";      
		}
		indent(); printf("%s      : ", fieldName);
		/* Not strictly true here, but we'll just assume we can print everything */
		printAscii((char *)atv->value.item.Data, atv->value.item.Length,
			atv->value.item.Length);
		putchar('\n');
	}
}
void P12BagAttrs::copyAttr(
	const NSS_Attribute &src,
	NSS_Attribute &dst)
{
	mCoder.allocCopyItem(src.attrType, dst.attrType);
	unsigned numVals = nssArraySize((const void **)src.attrValue);
	dst.attrValue = (CSSM_DATA **)p12NssNullArray(numVals, mCoder);
	for(unsigned dex=0; dex<numVals; dex++) {
		CSSM_DATA *dstVal = mCoder.mallocn<CSSM_DATA>();
		memset(dstVal, 0, sizeof(CSSM_DATA));
		dst.attrValue[dex] = dstVal;
		mCoder.allocCopyItem(*src.attrValue[dex], *dstVal);
	}
}
static int attrParse(
	const NSS_Attribute *attr,
	P12ParseInfo &pinfo, 
	unsigned depth)
{
	doIndent(depth);
	printf("attrType : %s\n", oidStr(attr->attrType, pinfo.mParser));
	unsigned numVals = nssArraySize((const void **)attr->attrValue);
	doIndent(depth);
	printf("numValues = %u\n", numVals);

	for(unsigned dex=0; dex<numVals; dex++) {
		doIndent(depth);
		printf("val[%u] : ", dex);
		
		/*
		 * Note: these two enumerated types should only have one att value 
		 * per PKCS9. Leave that to real apps, we want to see what's there
		 * in any case.
		 */
		if(nssCompareCssmData(&attr->attrType, &CSSMOID_PKCS9_FriendlyName)) {
			/* BMP string (UniCode) */
			CSSM_DATA ustr;
			if(pinfo.mCoder.decodeItem(*attr->attrValue[dex],
					kSecAsn1BMPStringTemplate, &ustr)) {
				printf("***Error decoding BMP string\n");
				continue;
			}
			printDataAsUnichars(ustr);
		}
		else if(nssCompareCssmData(&attr->attrType, 
					&CSSMOID_PKCS9_LocalKeyId)) {
			/* Octet string */
			CSSM_DATA ostr;
			if(pinfo.mCoder.decodeItem(*attr->attrValue[dex],
					kSecAsn1ObjectIDTemplate, &ostr)) {
				printf("***Error decoding LocalKeyId string\n");
				continue;
			}
			printDataAsHex(&ostr, 16);
		}
		else {
			printDataAsHex(attr->attrValue[dex], 8);
		}
	}
	return 0;
}
Esempio n. 8
0
/*
 * Parse an encoded NSS_P12_AuthenticatedSafe
 */
static int authSafeParse(pkcs12_context * context, const SecAsn1Item *authSafeBlob)
{
    p12DecodeLog("authSafeParse");
    NSS_P12_AuthenticatedSafe authSafe;
    memset(&authSafe, 0, sizeof(authSafe));
    require_noerr(decode_item(context, authSafeBlob, 
        NSS_P12_AuthenticatedSafeTemplate, &authSafe), out);

    unsigned numInfos = nssArraySize((const void **)authSafe.info);
    unsigned int dex;
    for (dex=0; dex<numInfos; dex++) {
        NSS_P7_DecodedContentInfo *info = authSafe.info[dex];
        require_noerr_quiet(authSafeElementParse(context, info), out);
    }
    return 0;
out:
    return -1;
}
/*
 * Parse an encoded NSS_P12_AuthenticatedSafe
 */
void P12Coder::authSafeParse(
	const CSSM_DATA &authSafeBlob,
	SecNssCoder &localCdr)
{
	p12DecodeLog("authSafeParse");

	NSS_P12_AuthenticatedSafe authSafe;
	
	memset(&authSafe, 0, sizeof(authSafe));
	if(localCdr.decodeItem(authSafeBlob,
			NSS_P12_AuthenticatedSafeTemplate,
			&authSafe)) {
		p12ErrorLog("Error decoding authSafe\n");
		P12_THROW_DECODE;
	}
	unsigned numInfos = nssArraySize((const void **)authSafe.info);
	for(unsigned dex=0; dex<numInfos; dex++) {
		NSS_P7_DecodedContentInfo *info = authSafe.info[dex];
		authSafeElementParse(info, localCdr);
	}
}
/* 
 * getter, public API version
 */
void P12BagAttrs::getAttr(
	unsigned			attrNum,
	CFDataRef			*attrOid,		// RETURNED
	CFArrayRef			*attrValues)	// RETURNED
{
	if(attrNum >= numAttrs()) {
		MacOSError::throwMe(paramErr);
	}
	NSS_Attribute *attr = mAttrs[attrNum];
	*attrOid = p12CssmDataToCf(attr->attrType);
	unsigned numVals = nssArraySize((const void **)attr->attrValue);
	if(numVals == 0) {
		/* maybe should return empty array...? */
		*attrValues = NULL;
		return;
	}
	CFMutableArrayRef vals = CFArrayCreateMutable(NULL, numVals, NULL);
	for(unsigned dex=0; dex<numVals; dex++) {
		CFDataRef val = p12CssmDataToCf(*attr->attrValue[dex]);
		CFArrayAppendValue(vals, val);
	}
	*attrValues = vals;
}
unsigned P12BagAttrs::numAttrs() const
{
	return nssArraySize((const void **)mAttrs);
}
Esempio n. 12
0
static int emit_item(pkcs12_context * context, NSS_Attribute **attrs, 
    CFStringRef item_key, CFTypeRef item_value)
{
    int result = -1;
	/* parse attrs into friendlyName, localKeyId; ignoring generic attrs */
    CFMutableDictionaryRef attr_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 
        0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    require(attr_dict, out);
	unsigned numAttrs = nssArraySize((const void **)attrs);
    unsigned int dex;
	for(dex = 0; dex < numAttrs; dex++) {
		NSS_Attribute *attr = attrs[dex];
		unsigned numValues = nssArraySize((const void**)attr->attrValue);
		DERItem type = { attr->attrType.Data, attr->attrType.Length };
		if(DEROidCompare(&type, &oidFriendlyName)) {
			/* 
			 * BMP string (UniCode). Spec says only one legal value.
			 */
			require(numValues == 1, out);
            SecAsn1Item friendly_name_asn1;
			require_noerr(decode_item(context, attr->attrValue[0],
					kSecAsn1BMPStringTemplate, &friendly_name_asn1), out);
            CFStringRef friendly_name = CFStringCreateWithBytes(kCFAllocatorDefault, 
                friendly_name_asn1.Data, friendly_name_asn1.Length, 
                kCFStringEncodingUnicode, true);
            if (friendly_name) {
                CFDictionarySetValue(attr_dict, kSecImportItemLabel, friendly_name);
                CFRelease(friendly_name);
            }
		}
		else if(DEROidCompare(&type, &oidLocalKeyId)) {
			/* 
			 * Octet string. Spec says only one legal value.
			 */
			require(numValues == 1, out);
            SecAsn1Item local_key_id;
			require_noerr(decode_item(context, attr->attrValue[0],
					kSecAsn1OctetStringTemplate, &local_key_id), out);
            CFDataRef keyid = CFDataCreate(kCFAllocatorDefault, local_key_id.Data, local_key_id.Length);
            if (keyid) {
                CFDictionarySetValue(attr_dict, kSecImportItemKeyID, keyid);
                CFRelease(keyid);
            }
		}
	}

    CFTypeRef key = CFDictionaryGetValue(attr_dict, kSecImportItemKeyID);
    if (!key)
        key = CFDictionaryGetValue(attr_dict, kSecImportItemLabel);
    if (!key)
        key = item_value;

    CFMutableDictionaryRef item = (CFMutableDictionaryRef)CFDictionaryGetValue(context->items, key);
    if (item) {
        CFDictionarySetValue(item, item_key, item_value);
    } else {
        CFDictionarySetValue(attr_dict, item_key, item_value);
        CFDictionarySetValue(context->items, key, attr_dict);
    }
    result = 0;
out:
    CFReleaseSafe(attr_dict);
    return result;
}
/*
 * Parse an encoded NSS_P12_SafeContents. This could be either 
 * present as plaintext in an AuthSafe or decrypted. 
 */
static int safeContentsParse(
	const CSSM_DATA &contentsBlob,
	P12ParseInfo &pinfo,
	unsigned depth)		// print indent depth
{
	NSS_P12_SafeContents sc;
	memset(&sc, 0, sizeof(sc));
	if(pinfo.mCoder.decodeItem(contentsBlob, NSS_P12_SafeContentsTemplate,
			&sc)) {
		printf("***Error decoding SafeContents\n");
		return 1;
	}
	unsigned numBags = nssArraySize((const void **)sc.bags);
	doIndent(depth);
	printf("SafeContents num bags %u\n", numBags);
	int rtn = 0;
	
	for(unsigned dex=0; dex<numBags; dex++) {
		NSS_P12_SafeBag *bag = sc.bags[dex];
		doIndent(depth);
		printf("Bag %u:\n", dex);
		
		/* common stuff here */
		doIndent(depth+3);
		printf("bagId = %s\n", oidStr(bag->bagId, pinfo.mParser));
		doIndent(depth+3);
		printf("type = %s\n", p12BagTypeStr(bag->type));
		unsigned numAttrs = nssArraySize((const void**)bag->bagAttrs);
		if(numAttrs) {
			doIndent(depth+3);
			printf("numAttrs = %u\n", numAttrs);
			for(unsigned i=0; i<numAttrs; i++) {
				doIndent(depth+3);
				printf("attr[%u]:\n", i);
				attrParse(bag->bagAttrs[i], pinfo, depth+6);
			}
		}
		
		/*
		 * Now break out to individual bag type
		 * 
		 * This hacked line breaks when we have a real key bag defined
		 */
		unsigned defaultLen = (unsigned)bag->bagValue.keyBag->Length;
		switch(bag->type) {
			case BT_KeyBag:
				doIndent(depth+3);
				printf("KeyBag: size %u\n", defaultLen);
				break;
			case BT_ShroudedKeyBag:
				doIndent(depth+3);
				printf("ShroudedKeyBag:\n");
				rtn = shroudedKeyBagParse(bag->bagValue.shroudedKeyBag,
					pinfo,
					depth+6);
				break;
			case BT_CertBag:
				doIndent(depth+3);
				printf("CertBag:\n");
				rtn = certBagParse(bag->bagValue.certBag,
					pinfo,
					depth+6);
				break;
			case BT_CrlBag:
				doIndent(depth+3);
				printf("CrlBag:\n");
				rtn = crlBagParse(bag->bagValue.crlBag,
					pinfo,
					depth+6);
				break;
			case BT_SecretBag:
				doIndent(depth+3);
				printf("SecretBag: size %u\n", defaultLen);
				break;
			case BT_SafeContentsBag:
				doIndent(depth+3);
				printf("SafeContentsBag: size %u\n", defaultLen);
				break;
			default:
				doIndent(depth+3);
				printf("===Warning: unknownBagType (%u)\n",
					(unsigned)bag->type);
				break;
		}
		if(rtn) {
			break;
		}
	}
	return rtn;
}
/*
 * ShroudedKeyBag parser w/decrypt
 */
static int shroudedKeyBagParse(
	const NSS_P12_ShroudedKeyBag *keyBag,
	P12ParseInfo &pinfo,
	unsigned depth)
{
	const CSSM_X509_ALGORITHM_IDENTIFIER &algId = keyBag->algorithm;
	NSS_P12_PBE_Params pbep;
	if(p12AlgIdParse(algId, &pbep, pinfo, depth)) {
		return 1;
	}
	if(pinfo.mPwd.Data == NULL) {
		doIndent(depth);
		printf("=== Key not decrypted (no passphrase)===\n");
		return 0;
	}

	/*
	 * Prepare for decryption
	 */
	CSSM_ALGORITHMS		keyAlg;			// e.g., CSSM_ALGID_DES
	CSSM_ALGORITHMS		encrAlg;		// e.g., CSSM_ALGID_3DES_3KEY_EDE
	CSSM_ALGORITHMS		pbeHashAlg;		// SHA1 or MD5
	uint32				keySizeInBits;
	uint32				blockSizeInBytes;	// for IV, optional
	CSSM_PADDING		padding;		// CSSM_PADDING_PKCS7, etc.
	CSSM_ENCRYPT_MODE	mode;			// CSSM_ALGMODE_CBCPadIV8, etc.
	#if IMPORT_EXPORT_COMPLETE
	PKCS_Which			pkcs;
	
	bool found = pkcsOidToParams(&algId.algorithm,
		keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
		padding, mode, pkcs);
	#else
	bool found = pkcsOidToParams(&algId.algorithm,
		keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
		padding, mode);
	#endif
	
	if(!found) {
		printf("***ShroudedKeyBag encrAlg not understood\n");
		return 1;
	}

	unsigned iterCount = dataToInt(pbep.iterations);
	CSSM_DATA berPrivKey;
	
	/* decrypt, result is BER encoded private key */
	CSSM_RETURN crtn = p12Decrypt_app(pinfo.mCspHand,
		keyBag->encryptedData,
		keyAlg, encrAlg, pbeHashAlg,
		keySizeInBits, blockSizeInBytes,
		padding, mode,
		iterCount, pbep.salt,
		pinfo.mPwd,
		pinfo.mCoder, 
		berPrivKey);
	if(crtn) {
		doIndent(depth);
		printf("***Error decrypting private key\n");
		return 1;
	}

	/* decode */
	NSS_PrivateKeyInfo privKey;
	memset(&privKey, 0, sizeof(privKey));
	if(pinfo.mCoder.decodeItem(berPrivKey,
			kSecAsn1PrivateKeyInfoTemplate, &privKey)) {
		doIndent(depth);
		printf("***Error decoding decrypted private key\n");
		return 1;
	}
	
	/* 
	 * in P12 library, we'd convert the result into a CSSM_KEY
	 * or a SecItem...
	 */
	CSSM_X509_ALGORITHM_IDENTIFIER &privAlg = privKey.algorithm;
	doIndent(depth);
	printf("Priv Key Alg  : %s\n", oidStr(privAlg.algorithm, pinfo.mParser));
	doIndent(depth);
	printf("Priv Key Blob : ");
	printDataAsHex(&privKey.privateKey, 16);
	
	unsigned numAttrs = nssArraySize((const void**)privKey.attributes);
	if(numAttrs) {
		doIndent(depth+3);
		printf("numAttrs = %u\n", numAttrs);
		for(unsigned i=0; i<numAttrs; i++) {
			doIndent(depth+3);
			printf("attr[%u]:\n", i);
			attrParse(privKey.attributes[i], pinfo, depth+6);
		}
	}
	return 0;
}