/*
 * Parse a NSS_P7_EncryptedData - specifically in the context
 * of a P12 in password privacy mode. (The latter assumption is
 * to enable us to infer CSSM_X509_ALGORITHM_IDENTIFIER.parameters
 * format). 
 */
static int encryptedDataParse(
	const NSS_P7_EncryptedData &edata,
	P12ParseInfo &pinfo,
	NSS_P12_PBE_Params *pbep,		// optional, RETURNED
	unsigned depth)					// print indent depth
{
	doIndent(depth);
	printf("version = %u\n", (unsigned)dataToInt(edata.version));
	const NSS_P7_EncrContentInfo &ci = edata.contentInfo;
	doIndent(depth);
	printf("contentType = %s\n", oidStr(ci.contentType, pinfo.mParser));
	
	/*
	 * Parse the alg ID, safe PBE params for when we do the 
	 * key unwrap
	 */
	const CSSM_X509_ALGORITHM_IDENTIFIER &algId = ci.encrAlg;
	if(p12AlgIdParse(algId, pbep, pinfo, depth)) {
		return 1;
	}
	
	doIndent(depth);
	printf("encrContent : ");
	printDataAsHex(&ci.encrContent, 12);
	return 0;
}
static int p12MacParse(
	const NSS_P12_MacData &macData, 
	P12ParseInfo &pinfo,
	unsigned depth)		// print indent depth
{
	if(p12AlgIdParse(macData.mac.digestAlgorithm, NULL, pinfo, depth)) {
		return 1;
	}
	doIndent(depth);
	printf("Digest : ");
	printDataAsHex(&macData.mac.digest, 20);
	doIndent(depth);
	printf("Salt : ");
	printDataAsHex(&macData.macSalt, 16);
	const CSSM_DATA &iter = macData.iterations;
	
	if(iter.Length > 4) {
		doIndent(depth);
		printf("***Warning: malformed iteraton length (%u)\n",
			(unsigned)iter.Length);
	}
	unsigned i = dataToInt(iter);
	doIndent(depth);
	printf("Iterations = %u\n", i);
	return 0;
}
static int p12Parse(
	const CSSM_DATA &rawBlob, 
	P12ParseInfo &pinfo,
	unsigned depth)		// print indent depth
{
	NSS_P12_DecodedPFX pfx;
	memset(&pfx, 0, sizeof(pfx));
	if(pinfo.mCoder.decodeItem(rawBlob, NSS_P12_DecodedPFXTemplate, &pfx)) {
		printf("***Error on top-level decode of NSS_P12_DecodedPFX\n");
		return 1;
	}
	doIndent(depth);
	printf("version = %u\n", (unsigned)dataToInt(pfx.version));
	NSS_P7_DecodedContentInfo &dci = pfx.authSafe;

	doIndent(depth);
	printf("contentType = %s\n", oidStr(dci.contentType, pinfo.mParser));
	doIndent(depth);
	printf("type = %s\n", p7ContentInfoTypeStr(dci.type));
	int rtn = 0;
	if(nssCompareCssmData(&dci.contentType, &CSSMOID_PKCS7_Data)) {
		doIndent(depth);
		printf("AuthenticatedSafe Length %u {\n", 
			(unsigned)dci.content.data->Length);
		rtn = authSafeParse(*dci.content.data, pinfo, depth+3);
		doIndent(depth);
		printf("}\n");
	}
	else {
		printf("Not parsing any other content type today.\n");
	}
	if(pfx.macData) {
		doIndent(depth);
		printf("Mac Data {\n");
		p12MacParse(*pfx.macData, pinfo, depth+3);
		doIndent(depth);
		printf("}\n");
		if(pinfo.mPwd.Data == NULL) {
			doIndent(depth);
			printf("=== MAC not verified (no passphrase)===\n");
		}
		else {
			CSSM_RETURN crtn = p12VerifyMac_app(pfx, pinfo.mCspHand, 
				pinfo.mPwd, pinfo.mCoder);
			doIndent(depth);
			if(crtn) {
				cssmPerror("p12VerifyMac", crtn);
				doIndent(depth);
				printf("***MAC verify failure.\n");
			}
			else {
				printf("MAC verifies OK.\n");
			}
		}
	}
	return 0;
}
static int encryptedDataDecrypt(
	const NSS_P7_EncryptedData &edata,
	P12ParseInfo &pinfo,
	NSS_P12_PBE_Params *pbep,	// preparsed
	CSSM_DATA &ptext)			// result goes here in pinfo.coder space
{
	/* see if we can grok the encr alg */
	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(&edata.contentInfo.encrAlg.algorithm,
		keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
		padding, mode, pkcs);
	#else
	bool found = pkcsOidToParams(&edata.contentInfo.encrAlg.algorithm,
		keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
		padding, mode);
	#endif  /* IMPORT_EXPORT_COMPLETE */
	
	if(!found) {
		printf("***EncryptedData encrAlg not understood\n");
		return 1;
	}
		
	unsigned iterCount = dataToInt(pbep->iterations);

	/* go */
	CSSM_RETURN crtn = p12Decrypt_app(pinfo.mCspHand,
		edata.contentInfo.encrContent,
		keyAlg, encrAlg, pbeHashAlg,
		keySizeInBits, blockSizeInBytes,
		padding, mode,
		iterCount, pbep->salt,
		pinfo.mPwd,
		pinfo.mCoder, 
		ptext);
	#if WRITE_DECRYPT_TEXT
	if(crtn == 0) {
		char fname[100];
		sprintf(fname, "decrypt%d.der", ctr++);
		writeFile(fname, ptext.Data, ptext.Length);
		printf("...wrote %u bytes to %s\n", 
			(unsigned)ptext.Length, fname);
	}
	#endif
	return crtn ? 1 : 0;
		
}
static int writeAuthSafeContent(
	const CSSM_DATA &rawBlob, 
	const char *outFile,
	SecNssCoder &coder,
	OidParser &parser)
{
	NSS_P12_RawPFX pfx;
	memset(&pfx, 0, sizeof(pfx));
	if(coder.decodeItem(rawBlob, NSS_P12_RawPFXTemplate, &pfx)) {
		printf("***Error on top-level decode of NSS_P12_RawPFX\n");
		return 1;
	}
	printf("...version = %u\n", (unsigned)dataToInt(pfx.version));
	NSS_P7_RawContentInfo &rci = pfx.authSafe;
	printf("...contentType = %s\n", oidStr(rci.contentType, parser));
	
	/* parse content per OID the only special case is PKCS7_Data,
	 * which we unwrap from an octet string before writing it */
	CSSM_DATA toWrite;
	if(nssCompareCssmData(&rci.contentType, &CSSMOID_PKCS7_Data)) {
		if(coder.decodeItem(rci.content, SEC_OctetStringTemplate,
				&toWrite)) {
			printf("***Error decoding PKCS7_Data Octet string; writing"
				" raw contents\n");
			toWrite = rci.content;
		}
	}
	else if(nssCompareCssmData(&rci.contentType, 
			&CSSMOID_PKCS7_SignedData)) {
		/* the only other legal content type here */
		/* This is encoded SignedData which I am not even close
		 * to worrying about - Panther p12 won't do this */
		toWrite = rci.content;
	}
	else {
		printf("***writeAuthSafeContent: bad contentType\n");
		return 1;
	}
	if(writeFile(outFile, toWrite.Data, toWrite.Length)) {
		printf("***Error writing to %s\n", outFile);
		return 1;
	}
	else {
		printf("...%u bytes written to %s\n", 
			(unsigned)toWrite.Length, outFile);
		return 0;
	}
}
/*
 * Parse an CSSM_X509_ALGORITHM_IDENTIFIER 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 p12AlgIdParse(
	const CSSM_X509_ALGORITHM_IDENTIFIER &algId,
	NSS_P12_PBE_Params *pbeParams,		// optional
	P12ParseInfo &pinfo,
	unsigned depth)						// print indent depth
{
	doIndent(depth);
	printf("encrAlg = %s\n", oidStr(algId.algorithm, pinfo.mParser));
	const CSSM_DATA &param = algId.parameters;
	if(pbeParams == NULL) {
		/* alg params are uninterpreted */
		doIndent(depth);
		printf("Alg Params : ");
		printDataAsHex(&param);
		return 0;
	}
	
	if(param.Length == 0) {
		printf("===warning: no alg parameters, this is not optional\n");
		return 0;
	}
	
	memset(pbeParams, 0, sizeof(*pbeParams));
	if(pinfo.mCoder.decodeItem(param, 
			NSS_P12_PBE_ParamsTemplate, pbeParams)) {
		printf("***Error decoding NSS_P12_PBE_Params\n");
		return 1;
	}
	doIndent(depth);
	printf("Salt : ");
	printDataAsHex(&pbeParams->salt);
	doIndent(depth);
	if(pbeParams->iterations.Length > 4) {
		printf("warning: iterations greater than max int\n");
		doIndent(depth);
		printf("Iterations : ");
		printDataAsHex(&pbeParams->iterations);
	}
	else {
		printf("Iterations : %u\n", 
			(unsigned)dataToInt(pbeParams->iterations));
	}
	return 0;
}
Пример #7
0
void PromelaDataModel::setVariable(void* ast, Data value) {
	PromelaParserNode* node = (PromelaParserNode*)ast;

	std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
	switch (node->type) {
	case PML_VAR_ARRAY: {
		PromelaParserNode* name = *opIter++;
		PromelaParserNode* expr = *opIter++;

		if (INVALID_ASSIGNMENT(name->value)) {
			ERROR_EXECUTION_THROW("Cannot assign to " + name->value);
		}

		int index = dataToInt(evaluateExpr(expr));

		if (_variables.compound.find(name->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		if (!_variables[name->value].hasKey("size")) {
			ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
		}

		if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
			ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
		}

		_variables.compound[name->value].compound["value"][index] = value;

		break;
	}
	case PML_NAME:
		if (INVALID_ASSIGNMENT(node->value)) {
			ERROR_EXECUTION_THROW("Cannot assign to " + node->value);
		}
		_variables.compound[node->value].compound["value"] = value;
		break;
	default:
		break;
	}

//	std::cout << Data::toJSON(_variables) << std::endl;
}
Пример #8
0
bool PromelaDataModel::dataToBool(const Data& data) {
	if (data.atom.size() == 0) // empty string or undefined
		return false;

	if (data.type == Data::VERBATIM) {
		// non-empty string is true
		return true;
	} else {
		if (data.atom.compare("true") == 0) {
			// boolean true is true
			return true;
		} else if (data.atom.compare("false") == 0) {
			return false;
		} else if (dataToInt(data) != 0) {
			return true; // non zero values are true
		}
	}
	return false;
}
int16_t Utils::blockForIntData(int16_t rID, int16_t aID, IncomingPacketReader *incomingPacketReader) {
  IncomingPacket p = blockForPacket(rID, aID, incomingPacketReader);
  return p.isEmpty() ? -1 : dataToInt(p.data);
}
/*
 * 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;
}
Пример #11
0
Data PromelaDataModel::getVariable(void* ast) {
	PromelaParserNode* node = (PromelaParserNode*)ast;
//	node->dump();

	std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
	switch(node->type) {
	case PML_NAME:
		if (_variables.compound.find(node->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + node->value + " was declared");
		}
//		if (_variables[node->value].compound.find("size") != _variables[node->value].compound.end()) {
//			ERROR_EXECUTION_THROW("Type error: Variable " + node->value + " is an array");
//		}
		return _variables[node->value]["value"];
	case PML_VAR_ARRAY: {
		PromelaParserNode* name = *opIter++;
		PromelaParserNode* expr = *opIter++;
		int index = dataToInt(evaluateExpr(expr));

		if (_variables.compound.find(name->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		if (!_variables[name->value].hasKey("size")) {
			ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
		}

		if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
			ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
		}
		return _variables.compound[name->value].compound["value"][index];
	}
	case PML_CMPND: {
//		node->dump();
//		std::cout << Data::toJSON(_variables["_event"]);

		std::stringstream idPath;
		PromelaParserNode* name = *opIter++;

		// special case for _x variables
		if (name->value.compare("_x") == 0) {
			PromelaParserNode* what = *opIter++;

			if (what->type == PML_VAR_ARRAY) {
				if (what->operands.size() == 2) {
					std::string arrName = what->operands.front()->value;
					std::string index = what->operands.back()->value;

					if (what->operands.back()->type == PML_STRING) {
						index = index.substr(1, index.size() - 2); // remove quotes
					}

					if (arrName.compare("states") == 0) {
						return Data(_interpreter->isInState(index));
					}
				}
			}
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		if (_variables.compound.find(name->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		Data currData = _variables.compound[name->value]["value"];
		idPath << name->value;
		while(opIter != node->operands.end()) {
			std::string key = (*opIter)->value;
			idPath << "." << key;
			if (currData.compound.find(key) == currData.compound.end()) {
				ERROR_EXECUTION_THROW("No variable " + idPath.str() + " was declared");
			}
			Data tmp = currData.compound[key];
			currData = tmp;

			opIter++;
		}
		return currData;
	}
	default:
		ERROR_EXECUTION_THROW("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented");
	}
	return 0;
}
Пример #12
0
Data PromelaDataModel::evaluateExpr(void* ast) {
	PromelaParserNode* node = (PromelaParserNode*)ast;
	std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
	switch (node->type) {
	case PML_CONST:
		if (iequals(node->value, "false"))
			return Data(false);
		if (iequals(node->value, "true"))
			return Data(true);
		return strTo<int>(node->value);
	case PML_NAME:
	case PML_VAR_ARRAY:
	case PML_CMPND:
		return getVariable(node);
	case PML_STRING: {
		std::string stripped = node->value.substr(1, node->value.size() - 2);
		return Data(stripped, Data::VERBATIM);
	}
	case PML_PLUS:
		return dataToInt(evaluateExpr(*opIter++)) + dataToInt(evaluateExpr(*opIter++));
	case PML_MINUS:
		return dataToInt(evaluateExpr(*opIter++)) - dataToInt(evaluateExpr(*opIter++));
	case PML_DIVIDE:
		return dataToInt(evaluateExpr(*opIter++)) / dataToInt(evaluateExpr(*opIter++));
	case PML_MODULO:
		return dataToInt(evaluateExpr(*opIter++)) % dataToInt(evaluateExpr(*opIter++));
	case PML_EQ: {
		PromelaParserNode* lhs = *opIter++;
		PromelaParserNode* rhs = *opIter++;

		Data left = evaluateExpr(lhs);
		Data right = evaluateExpr(rhs);

		if (left == right) // overloaded operator==
			return Data(true);

		// literal strings or strings in variables
		if ((lhs->type == PML_STRING || rhs->type == PML_STRING)
		        || (left.type == Data::VERBATIM && right.type == Data::VERBATIM)) {
			return (left.atom.compare(right.atom) == 0 ? Data(true) : Data(false));
		}
		return dataToInt(left) == dataToInt(right);
	}
	case PML_NEG:
		return !dataToBool(evaluateExpr(*opIter++));
	case PML_LT:
		return dataToInt(evaluateExpr(*opIter++)) < dataToInt(evaluateExpr(*opIter++));
	case PML_LE:
		return dataToInt(evaluateExpr(*opIter++)) <= dataToInt(evaluateExpr(*opIter++));
	case PML_GT:
		return dataToInt(evaluateExpr(*opIter++)) > dataToInt(evaluateExpr(*opIter++));
	case PML_GE:
		return dataToInt(evaluateExpr(*opIter++)) >= dataToInt(evaluateExpr(*opIter++));
	case PML_TIMES:
		return dataToInt(evaluateExpr(*opIter++)) * dataToInt(evaluateExpr(*opIter++));
	case PML_LSHIFT:
		return dataToInt(evaluateExpr(*opIter++)) << dataToInt(evaluateExpr(*opIter++));
	case PML_RSHIFT:
		return dataToInt(evaluateExpr(*opIter++)) >> dataToInt(evaluateExpr(*opIter++));
	case PML_AND:
	case PML_OR: {
		PromelaParserNode* lhs = *opIter++;
		PromelaParserNode* rhs = *opIter++;

		std::cout << "-----" << std::endl;
		lhs->dump();
		rhs->dump();

		Data left = evaluateExpr(lhs);
		Data right = evaluateExpr(rhs);

		bool truthLeft = dataToBool(left);
		bool truthRight = dataToBool(right);

		if (node->type == PML_AND) {
			return truthLeft && truthRight;
		} else {
			return truthLeft || truthRight;
		}
	}
	default:
		ERROR_EXECUTION_THROW("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented");
	}
	return 0;
}
Пример #13
0
void PromelaDataModel::evaluateDecl(void* ast) {
	PromelaParserNode* node = (PromelaParserNode*)ast;
	if (false) {
	} else if (node->type == PML_DECL) {
		std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
		PromelaParserNode* vis = *opIter++;
		PromelaParserNode* type = *opIter++;
		PromelaParserNode* varlist = *opIter++;

		for (std::list<PromelaParserNode*>::iterator nameIter = varlist->operands.begin();
		        nameIter != varlist->operands.end();
		        nameIter++) {
			Data variable;
			variable.compound["vis"] = Data(vis->value, Data::VERBATIM);
			variable.compound["type"] = Data(type->value, Data::VERBATIM);

			if (false) {
			} else if ((*nameIter)->type == PML_NAME) {
				// plain variables without initial assignment

				if (type->value == "mtype") {
					variable.compound["value"] = Data(_lastMType++, Data::INTERPRETED);
				} else {
					variable.compound["value"] = Data(0, Data::INTERPRETED);
				}
				_variables.compound[(*nameIter)->value] = variable;

			} else if ((*nameIter)->type == PML_ASGN) {
				// initially assigned variables

				std::list<PromelaParserNode*>::iterator opIterAsgn = (*nameIter)->operands.begin();
				PromelaParserNode* name = *opIterAsgn++;
				PromelaParserNode* expr = *opIterAsgn++;

				variable.compound["value"] = evaluateExpr(expr);

				assert(opIterAsgn == (*nameIter)->operands.end());
				_variables.compound[name->value] = variable;
			} else if ((*nameIter)->type == PML_VAR_ARRAY) {
				// variable arrays

				std::list<PromelaParserNode*>::iterator opIterAsgn = (*nameIter)->operands.begin();
				PromelaParserNode* name = *opIterAsgn++;
				int size = dataToInt(evaluateExpr(*opIterAsgn++));

				variable.compound["size"] = size;
				for (int i = 0; i < size; i++) {
					variable.compound["value"].array.push_back(Data(0, Data::INTERPRETED));
				}

				assert(opIterAsgn == (*nameIter)->operands.end());
				_variables.compound[name->value] = variable;

			} else {
				ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented");
			}
		}
		assert(opIter == node->operands.end());
	} else if (node->type == PML_DECLLIST) {
		for (std::list<PromelaParserNode*>::iterator declIter = node->operands.begin();
		        declIter != node->operands.end();
		        declIter++) {
			evaluateDecl(*declIter);
		}
	} else {
		ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented");
	}
}