/* * ShroudedKeyBag parser w/decrypt */ static int shroudedKeyBagParse(pkcs12_context * context, const NSS_P12_SafeBag *safeBag) { p12DecodeLog("Found shrouded key bag"); const NSS_P12_ShroudedKeyBag *keyBag = safeBag->bagValue.shroudedKeyBag; SecAsn1Item ptext = {0, NULL}; require_noerr_quiet(p12Decrypt(context, &keyBag->algorithm, &keyBag->encryptedData, &ptext), out); /* Decode PKCS#8 formatted private key */ NSS_PrivateKeyInfo pki; memset(&pki, 0, sizeof(pki)); require_noerr(decode_item(context, &ptext, kSecAsn1PrivateKeyInfoTemplate, &pki), out); DERItem algorithm = { pki.algorithm.algorithm.Data, pki.algorithm.algorithm.Length }; require(DEROidCompare(&oidRsa, &algorithm), out); CFDataRef keyData = CFDataCreate(kCFAllocatorDefault, pki.privateKey.Data, pki.privateKey.Length); require_noerr(emit_item(context, safeBag->bagAttrs, CFSTR("key"), keyData), out); CFRelease(keyData); return 0; out: return -1; }
/* * 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; }
inline PyObject* decode_from_stream(const std::string& enc_rule, hu::InStream& stream) { PyObject* res = PyTuple_New(enc_rule.size()); for(std::size_t i = 0; i < enc_rule.size(); ++i) { PyObject* v = decode_item(enc_rule[i], stream); if (v == NULL) { return NULL; } PyTuple_SET_ITEM(res, i, v); } return res; }
/* * Parse an SecAsn1AlgId specific to P12. * Decode the alg params as a NSS_P12_PBE_Params and parse and * return the result if the pbeParams is non-NULL. */ static int algIdParse(pkcs12_context * context, const SecAsn1AlgId *algId, NSS_P12_PBE_Params *pbeParams/*optional*/) { p12DecodeLog("algIdParse"); const SecAsn1Item *param = &algId->parameters; require(pbeParams, out); require(param && param->Length, out); memset(pbeParams, 0, sizeof(*pbeParams)); require_noerr(decode_item(context, param, NSS_P12_PBE_ParamsTemplate, pbeParams), out); return 0; out: return -1; }
/* * 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; }
p12_error p12decode(pkcs12_context * context, CFDataRef cdpfx) { int err = p12_decodeErr; NSS_P12_DecodedPFX pfx; memset(&pfx, 0, sizeof(pfx)); SecAsn1Item raw_blob = { CFDataGetLength(cdpfx), (void*)CFDataGetBytePtr(cdpfx) }; require_noerr_quiet(decode_item(context, &raw_blob, NSS_P12_DecodedPFXTemplate, &pfx), out); NSS_P7_DecodedContentInfo *dci = &pfx.authSafe; /* only support CT_Data at top level (password based integrity mode) */ require(dci->type == CT_Data, out); require(pfx.macData, out); require_noerr_action_quiet(p12VerifyMac(context, &pfx), out, err = p12_passwordErr); require_noerr_quiet(authSafeParse(context, dci->content.data), out); return errSecSuccess; out: return err; }
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; }