//---------------------------------------------------------------------------- // // Copyright (C) 2006 Intel Corporation // // File: ConfigFile.cpp // // Contents: Tool to create and view sample Intel(R) AMT USB format files // used with the Configuration Server. // //---------------------------------------------------------------------------- #include "SetupFileReaderWriter.h" #include "ConfigFile.h" #include "SetupFileDefinitions.h" #include #include using namespace std; #include // check if file exists bool MyFileExists(const string& fileName) { ifstream in(fileName.c_str(), ios_base::binary); if(in.is_open()) { in.close(); return true; } in.clear(ios::failbit); in.close(); return false; } bool IsPskAllZeroes(const char pid[PID_LENGTH], const char pps[PPS_LENGTH]) { // check pid for all zeroes for(int i = 0; i < PID_LENGTH; i++) { if (48 != pid[i]) { return false; } } // check pps for all zeroes for(int i = 0; i < PPS_LENGTH; i++) { if (48 != pps[i]) { return false; } } return true; } bool IsPpsValid(const char pps[PPS_LENGTH]) { // first validate char values for(int i = 0; i < PPS_LENGTH; i++) { unsigned int tmp = (unsigned int)pps[i]; if(!((tmp > 47 && tmp < 58) || (tmp > 64 && tmp < 91))) { return false; } } // validate CRC mechanism for(int i = 0; i < 8; i++) { unsigned int crc = 0; for(int j = 0; j < 3; j ++) { crc += pps[i*4 + j]; } crc %= 36; if(crc < 10) { crc = crc + 48; } else { crc = crc - 10 + 65; } if(crc != (unsigned int)pps[i*4 + 3]) { return false; } } return true; } bool IsPidValid(const char pid[PID_LENGTH]) { // first validate char values for(int i = 0; i < PID_LENGTH; i++) { unsigned int tmp = (unsigned int)pid[i]; if(!((tmp > 47 && tmp < 58) || (tmp > 64 && tmp < 91))) { return false; } } // validate CRC mechanism unsigned int crc = 0; for(int i = 0; i < 7; i++) { crc += pid[i]; } crc %= 36; if(crc < 10) { crc = crc + 48; } else { crc = crc - 10 + 65; } if(crc != (unsigned int)pid[7]) { return false; } return true; } bool IsPasswordValid(const string& pwd) { // validate length int len = (int)pwd.length(); if(len < MIN_PWD_LEN || len > MAX_PWD_LEN) { return false; } // verify password strength bool digit = false; bool symbol = false; bool upper = false; bool lower = false; for (int i = 0; i < len; i++) { // make sure that we have only acceptable characters if ((pwd[i] == ':') || (pwd[i] == '"') || (pwd[i] == ',') || (pwd[i] < 0x20) || (pwd[i] > 0x7E)) { //printf("\nError: The given password contains an invalid character.\n"); return false; } // lower case abc if (pwd[i] >= 'a' && pwd[i] <= 'z') { lower = true; } // upper case ABC else if (pwd[i] >= 'A' && pwd[i] <= 'Z') { upper = true; } // numeric else if (pwd[i] >= '0' && pwd[i] <= '9') { digit = true; } // 7 bit ASCII non alpha numeric else if (pwd[i] != '_' && pwd[i] != ' ') { symbol = true; } } if(!(symbol && digit && upper && lower)) { //printf("\nError: The given password is not strong.\n"); return false; } return true; } int IsRecordValid(const ConfigRecord record) { if (record.hasPskPair) { if (!IsPskAllZeroes((char*)(record.Pid), (char*)(record.Pps))) { if(!IsPidValid((char*)(record.Pid))) { return CONFIG_INVALID_PID; } if(!IsPpsValid((char*)(record.Pps))) { return CONFIG_INVALID_PPS; } } } if(!IsPasswordValid(record.NewMEBxPwd)) { return CONFIG_INVALID_NEW_PWD; } if(record.CurrentMEBxPwd.length() > MAX_PWD_LEN || record.CurrentMEBxPwd.length() == 0) { return CONFIG_INVALID_CURR_PWD; } if(!record.valid) { return CONFIG_INVALID_RECORD; } return CONFIG_SUCCESS; } void RandomChar(char* randomChar, const string& validChars, const MyRand* myRand) { int length = (int)validChars.length(); int index = myRand->RandomNumber() % length; if(randomChar) { *randomChar = validChars[index]; } } int RandomPassword(string* pwd, const unsigned int len, MyRand* myRand) { bool randIsNull = false; int length = len; string data; data.resize(length); const string CAPITALS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string LOWER_CASE = "abcdefghijklmnopqrstuvwxyz"; const string DIGITS = "0123456789"; const string SYMBOLS = "!#$%&'()*+-./;<=>?@{\\]^`{|}~"; const string all = CAPITALS + LOWER_CASE + DIGITS + SYMBOLS + " _"; if(length < MIN_PWD_LEN) { length = MIN_PWD_LEN; } if(length > MAX_PWD_LEN) { length = MAX_PWD_LEN; } if(myRand == NULL) { randIsNull = true; try { myRand = new MyRand(); } catch(RandomNumberError) { delete myRand; return CONFIG_RNG_ERROR; } } int retVal = CONFIG_SUCCESS; try { // choose random index for capital, lowercase, symbol and digit int indexes[MAX_PWD_LEN]; for(int i = 0; i < MAX_PWD_LEN; i++) { indexes[i] = i; } int r = myRand->RandomNumber() % length; int capitalIndex = indexes[r]; indexes[r] = indexes[length - 1]; r = myRand->RandomNumber() % (length - 1); int lowerIndex = indexes[r]; indexes[r] = indexes[length - 2]; r = myRand->RandomNumber() % (length - 2); int symbolIndex = indexes[r]; indexes[r] = indexes[length - 3]; r = myRand->RandomNumber() % (length - 3); int digitIndex = indexes[r]; char temp; for(int i = 0; i < length; i++) { if(i == capitalIndex) { RandomChar(&temp, CAPITALS, myRand); } else if(i == lowerIndex) { RandomChar(&temp, LOWER_CASE, myRand); } else if(i == symbolIndex) { RandomChar(&temp, SYMBOLS, myRand); } else if(i == digitIndex) { RandomChar(&temp, DIGITS, myRand); } else { RandomChar(&temp, all, myRand); } data[i] = temp; } } catch(RandomNumberError) { retVal = CONFIG_RNG_ERROR; } if(randIsNull) { delete myRand; myRand = NULL; } if(retVal == CONFIG_SUCCESS) { if(pwd) { *pwd = data; } } return retVal; } int RandomPid(char pid[PID_LENGTH], const MyRand* myRand) { bool randIsNull = false; const string LEGAL = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if(myRand == NULL) { randIsNull = true; try { myRand = new MyRand(); } catch(RandomNumberError) { delete myRand; return CONFIG_RNG_ERROR; } } int retVal = CONFIG_SUCCESS; char temp; unsigned int crc = 0; try { for(int i = 0; i < 7; i++) { RandomChar(&temp, LEGAL, myRand); pid[i] = temp; crc += (unsigned char)pid[i]; } crc %= 36; pid[7] = LEGAL[crc]; } catch(RandomNumberError) { retVal = CONFIG_RNG_ERROR; } if(randIsNull) { delete myRand; myRand = NULL; } return retVal; } int RandomPps(char pps[PPS_LENGTH], const MyRand* myRand) { bool randIsNull = false; const string LEGAL = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if(myRand == NULL) { randIsNull = true; try { myRand = new MyRand(); } catch(RandomNumberError) { delete myRand; return CONFIG_RNG_ERROR; } } int retVal = CONFIG_SUCCESS; char temp; unsigned int crc = 0; try { for(int i = 0; i < 8; i++) { crc = 0; for(int j = 0; j < 3; j ++) { RandomChar(&temp, LEGAL, myRand); pps[i*4 + j] = temp; crc += (unsigned char)pps[i*4 + j]; } crc %= 36; pps[i*4 + 3] = LEGAL[crc]; } } catch(RandomNumberError) { retVal = CONFIG_RNG_ERROR; } if(randIsNull) { delete myRand; myRand = NULL; } return retVal; } int WriteVersion1ConfigFile(const string& fileName, const vector& records, const bool overwrite) { int retVal = CONFIG_SUCCESS; unsigned int number = (unsigned int)records.size(); for(unsigned int i = 0; i < number; i++) { if((retVal = IsRecordValid(records[i])) != CONFIG_SUCCESS) { return retVal; } } if(!overwrite && MyFileExists(fileName)) { return CONFIG_FILE_WRITE_ERROR; } vector dataRecords; ConfigRecord temp; for(unsigned int i = 0; i < number; i++) { temp = records[i]; DataRecord record; // default Ctr record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD, (unsigned short)temp.CurrentMEBxPwd.length(), (unsigned char*)temp.CurrentMEBxPwd.c_str()); record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD, (unsigned short)temp.NewMEBxPwd.length(), (unsigned char*)temp.NewMEBxPwd.c_str()); if (temp.hasPskPair) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PID, PID_LENGTH, (unsigned char*)temp.Pid); record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PPS, PPS_LENGTH, (unsigned char*)temp.Pps); } dataRecords.push_back(record); } unsigned short headerChunkCount = SINGLE_CHUNK_COUNT; unsigned short dataRecordChunkCount = SINGLE_CHUNK_COUNT; unsigned int bufferLength = (unsigned int)CHUNK_SIZE * (headerChunkCount + number * dataRecordChunkCount); unsigned char* data = new unsigned char[bufferLength]; memset(data, 0, bufferLength); SetupFileInfo fileInfo; fileInfo.consumeRecords = false; fileInfo.dataRecordChunkCount = dataRecordChunkCount; fileInfo.headerChunkCount = headerChunkCount; fileInfo.majorVersion = SETUP_FILE_VERSION_1; fileInfo.minorVersion = 0; fileInfo.recordCount = number; fileInfo.recordsConsumed = 0; retVal = RecordsToBuffer(dataRecords, fileInfo, bufferLength, data); if(retVal == CONFIG_SUCCESS) { ofstream setupFile(fileName.c_str(), ios_base::binary); if(!setupFile.is_open()) { retVal = CONFIG_FILE_WRITE_ERROR; } else { setupFile.write((char*)data,bufferLength); setupFile.close(); } } delete[] data; data = NULL; return retVal; } int GetConfigRecord(const DataRecord record, ConfigRecord* config) { unsigned short varLen; char pid[PID_LENGTH]; char pps[PPS_LENGTH]; char currPwdB[MAX_PWD_LEN + 1]; char newPwdB[MAX_PWD_LEN + 1]; if(!record.FindEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD, &varLen, MAX_PWD_LEN, (unsigned char*)currPwdB)) { return CONFIG_MISSING_CURR_PWD; } if(varLen == 0 || varLen > MAX_PWD_LEN) { return CONFIG_INVALID_CURR_PWD; } currPwdB[varLen] = 0; if(!record.FindEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD, &varLen, MAX_PWD_LEN, (unsigned char*)newPwdB)) { return CONFIG_MISSING_NEW_PWD; } if(varLen < MIN_PWD_LEN || varLen > MAX_PWD_LEN) { return CONFIG_INVALID_NEW_PWD; } newPwdB[varLen] = 0; if(!IsPasswordValid((char*)newPwdB)) { return CONFIG_INVALID_NEW_PWD; } if(!record.FindEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PID, &varLen, PID_LENGTH, (unsigned char*)pid)) { return CONFIG_MISSING_PID; } if(varLen != PID_LENGTH) { return CONFIG_INVALID_PID; } if(!record.FindEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PPS, &varLen, PPS_LENGTH, (unsigned char*)pps)) { return CONFIG_MISSING_PPS; } if(varLen != PPS_LENGTH) { return CONFIG_INVALID_PPS; } if (!IsPskAllZeroes(pid, pps)) { if (!IsPidValid(pid)) { return CONFIG_INVALID_PID; } if (!IsPpsValid(pps)) { return CONFIG_INVALID_PPS; } } config->valid = true; config->CurrentMEBxPwd = (char*)currPwdB; config->NewMEBxPwd = (char*)newPwdB; if (memcpy_s((char*)(config->Pid), PID_LENGTH, (char*)pid, PID_LENGTH)) { return CONFIG_INVALID_PID; } if (memcpy_s((char*)(config->Pps), PPS_LENGTH, (char*)pps, PPS_LENGTH)) { return CONFIG_INVALID_PPS; } return CONFIG_SUCCESS; } int ReadConfigFile(const string& fileName, vector& records) { ifstream ifs(fileName.c_str(), ifstream::binary); if(!ifs.is_open()) { return CONFIG_FILE_READ_ERROR; } ifs.seekg(0,ifstream::end); unsigned int fileSize = ifs.tellg(); ifs.seekg(0); unsigned char* data = new unsigned char[fileSize]; ifs.read((char*)data, fileSize); ifs.close(); vector dataRecords; SetupFileInfo fileInfo; int retVal = BufferToRecords(fileSize, data, &fileInfo, &dataRecords); delete[] data; data = NULL; if(retVal != CONFIG_SUCCESS) { return retVal; } unsigned int numRecords = (unsigned int)dataRecords.size(); for(unsigned int i = 0; i < numRecords; i++) { ConfigRecord temp; if(dataRecords[i].GetIsValid()) { retVal = GetConfigRecord(dataRecords[i], &temp); if(retVal != CONFIG_SUCCESS) { return retVal; } } else { temp.valid = false; } records.push_back(temp); } return retVal; } int GetConfigFileRecord(const string& fileName, const unsigned int index, ConfigRecord* config) { ifstream ifs(fileName.c_str(), ifstream::binary); if(!ifs.is_open()) { return CONFIG_FILE_READ_ERROR; } ifs.seekg(0,ifstream::end); unsigned int fileSize = ifs.tellg(); ifs.seekg(0); unsigned char* data = new unsigned char[fileSize]; ifs.read((char*)data, fileSize); ifs.close(); DataRecord record; int retVal = GetRecordByIndex(fileSize, data, index, &record); delete[] data; data = NULL; if(retVal != CONFIG_SUCCESS) { return retVal; } return GetConfigRecord(record, config); } int CreateDataRecord(const RecordSettings& settings, DataRecord& record) { /*********** Start of ME Kernel Variable Identifiers **********/ unsigned short currPwdLen = (unsigned short)settings.currentMEBxPwd.length(); if(currPwdLen == 0 || currPwdLen > MAX_PWD_LEN) { return CONFIG_INVALID_CURR_PWD; } if(!IsPasswordValid(settings.newMEBxPwd)) { return CONFIG_INVALID_NEW_PWD; } // Current MEBx password (all versions) record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD, currPwdLen, (unsigned char*)settings.currentMEBxPwd.c_str()); // New MEBx password (all versions) record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD, (unsigned short)settings.newMEBxPwd.length(), (unsigned char*)settings.newMEBxPwd.c_str()); // Manageability Feature Selection (all versions) if(settings.setAmt) { unsigned char man = ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_AMT; record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION, ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_LEN, &man); } if(((2 == settings.majorVersion) && (1 == settings.minorVersion)) || (3 <= settings.majorVersion)) { // Firmware Local Update (ver 2.1, 3 and 4) if(settings.fwLocalUpdatePresent) { if((settings.fwLocalUpdateEnable == LOCAL_FW_UPDATE_PASSWORD_PROTECTED && 4 <= settings.majorVersion) || settings.fwLocalUpdateEnable == LOCAL_FW_UPDATE_DISABLED || settings.fwLocalUpdateEnable == LOCAL_FW_UPDATE_ENABLED) { unsigned char fwLocalUpdate = (unsigned char)settings.fwLocalUpdateEnable; record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_FW_LOCAL_UPDATE, ME_VARIABLE_IDENTIFIER_FW_LOCAL_UPDATE_LEN, &fwLocalUpdate); } } } if(((2 == settings.majorVersion) && (1 == settings.minorVersion)) || (3 == settings.majorVersion)) { // Firmware Update Qualifier (ver 2.1 and 3) if (settings.fwUpdateQualifierPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_FW_UPDATE_QUALIFIER, ME_VARIABLE_IDENTIFIER_FW_UPDATE_QUALIFIER_LEN, (const unsigned char *)&settings.fwUpdateQualifier); } } if(((2 == settings.majorVersion) && (1 == settings.minorVersion)) || (3 <= settings.majorVersion)) { // Power Packages (ver 2.1, 3 and 4) if (settings.guidPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_ME_KERNEL, ME_VARIABLE_IDENTIFIER_PP, ME_VARIABLE_IDENTIFIER_PP_LEN, (const unsigned char *)settings.guid); } } /*********** End of ME Kernel Variable Identifiers **********/ /*********** Start of Intel(R) AMT CM Variable Identifiers **********/ // PID (all versions) if(settings.pidValid) { if (!IsPskAllZeroes(settings.pid, settings.pps)) { if(!IsPidValid(settings.pid)) { return CONFIG_INVALID_PID; } } record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PID, PID_LENGTH, (unsigned char*)&(settings.pid[0])); } // PPS (all versions) if(settings.ppsValid) { if (!IsPskAllZeroes(settings.pid, settings.pps)) { if(!IsPpsValid(settings.pps)) { return CONFIG_INVALID_PPS; } } record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PPS, PPS_LENGTH, (unsigned char*)&(settings.pps[0])); } if(settings.majorVersion >= 2) { // PKI DNS Suffix (ver 2, 2.1, 3 and 4) if(settings.dnsSuffixValid) { if((settings.dnsSuffix.length() > CM_VARIABLE_IDENTIFIER_PKI_DNS_SUFFIX_MAXLEN) || (settings.dnsSuffix.empty())) { return CONFIG_INVALID_DNS_SUFFIX; } record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PKI_DNS_SUFFIX, (unsigned short)settings.dnsSuffix.length(), (unsigned char*)settings.dnsSuffix.c_str()); } // Config Server FQDN (ver 2, 2.1, 3 and 4) if(settings.serverFqdnValid) { if((settings.ServerFqdn.length() > CM_VARIABLE_IDENTIFIER_CONFIG_SERVER_FQDN_MAXLEN) || (settings.ServerFqdn.empty())) { return CONFIG_INVALID_FQDN; } record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_CONFIG_SERVER_FQDN, (unsigned short)settings.ServerFqdn.length(), (unsigned char*)settings.ServerFqdn.c_str()); } // RCFG Enabled (ver 2, 2.1, 3 and 4) if(settings.enableRCFGValid) { unsigned char rcfg = CM_VARIABLE_IDENTIFIER_RCFG_ENABLED_OFF; if(settings.enableRCFG) { rcfg = CM_VARIABLE_IDENTIFIER_RCFG_ENABLED_ON; } record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_RCFG_ENABLED, CM_VARIABLE_IDENTIFIER_RCFG_ENABLED_LEN, &rcfg); } // Pre Installed (OEM) Cert Enable (ver 2, 2.1, 3 and 4) if(settings.oemCertificateFlagExist) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PREINSTALLED_CERT_ENABLE, CM_VARIABLE_IDENTIFIER_PREINSTALLED_CERT_ENABLE_LEN, (const unsigned char *)&settings.oemCertificateFlag); } // Pre Installed (OEM) Cert Enable (ver 2, 2.1, 3 and 4) if(settings.userCertificateFlagExist) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG, CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG_LEN, (const unsigned char *)&settings.userCertificateFlag); } if(!settings.certHashes.empty()) { //// Pre Installed Cert Enable (ver 2, 2.1, 3 and 4) //// Disable default //unsigned char tmp = CM_VARIABLE_IDENTIFIER_PREINSTALLED_CERT_ENABLE_OFF; //record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, // CM_VARIABLE_IDENTIFIER_PREINSTALLED_CERT_ENABLE, // CM_VARIABLE_IDENTIFIER_PREINSTALLED_CERT_ENABLE_LEN, &tmp); // User Defined Certs Config (ver 2, 2.1, 3 and 4) // Delete existing user defined hashes /*tmp = CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG_DELETE; record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG, CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG_LEN, &tmp);*/ // User Defined Cert Add (ver 2, 2.1, 3 and 4) // Add new certs unsigned char hash[CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD_MAXLEN]; for(unsigned int i = 0; i < settings.certHashes.size(); i++) { // SHA1 supported in ver 2, 2.1, 3 and 4 while SHA256 and SHA384 supported in ver 3 and 4 only; // Therefore, add the cert to the file only if it stands in the described terms. if ( (USB_CERT_HASH_ALGORITHM_SHA1 == settings.certHashes[i]._hashAlgorithm) || ((USB_CERT_HASH_ALGORITHM_SHA256 == settings.certHashes[i]._hashAlgorithm || (USB_CERT_HASH_ALGORITHM_SHA384 == settings.certHashes[i]._hashAlgorithm)) && (3 <= settings.majorVersion))) { hash[0] = settings.certHashes[i]._hashAlgorithm; if(memcpy_s(hash + 1, ARRAYSIZE(hash) - 1, settings.certHashes[i]._hash, settings.certHashes[i]._hashLength)) { return CONFIG_INVALID_CERT_SETTINGS; } memset(hash + 1 + settings.certHashes[i]._hashLength, 0, CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD_MAXLEN - (1 + settings.certHashes[i]._hashLength)); // Friendly name length is assumed to be <= 32 *(hash + 1 + settings.certHashes[i]._hashLength) = (unsigned char)settings.certHashes[i]._friendlyName.length(); if (memcpy_s(hash + 1 + settings.certHashes[i]._hashLength + 1, ARRAYSIZE(hash) - settings.certHashes[i]._hashLength -2, settings.certHashes[i]._friendlyName.c_str(), settings.certHashes[i]._friendlyName.length())) { return CONFIG_INVALID_CERT_SETTINGS; } record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD, 1 + settings.certHashes[i]._hashLength + 1 + (unsigned short)settings.certHashes[i]._friendlyName.length(), hash); } } } // SOL IDER Config (ver 2, 2.1,3 and 4) if(settings.soliderConfigValid) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SOL_IDE_REDIRECTION_CONFIG, CM_VARIABLE_IDENTIFIER_SOL_IDE_REDIRECTION_CONFIG_LEN, &settings.soliderConfig); } } if(((2 == settings.majorVersion) && (1 == settings.minorVersion)) || (3 <= settings.majorVersion)) { // Host Name (ver 2.1, 3 and 4) if (settings.hostNamePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_HOST_NAME, (unsigned short)settings.hostName.length(), (const unsigned char *)settings.hostName.c_str()); } // Domain Name (ver 2.1, 3 and 4) if (settings.domainNamePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_DOMAIN_NAME, (unsigned short)settings.domainName.length(), (const unsigned char *)settings.domainName.c_str()); } // DHCP (ver 2.1, 3 and 4) if (settings.dhcpPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_DHCP, DHCP_LENGTH, (const unsigned char *)&settings.dhcp); } // Secure Firmware Update (ver 2.1 and 3) if (3 >= settings.majorVersion && settings.secureFWUpdatePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SFWU, SFWU_LENGTH, (const unsigned char *)&settings.secureFWUpdate); } // Idle timeout (ver 2.1, 3 and 4) if (settings.idleTimeOutPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_ITO, IDLE_TIMEOUT_LENGTH, (const unsigned char *)settings.idleTimeOut); } // Provisioning Mode (ver 2.1, deprecated from 3) if (settings.provisionModePresent) { if (3 <= settings.majorVersion) { cout << endl << "Warning: Entering the 'Provisioning Mode' variable (configured using the '-pm' flag)" << endl << "\t to the file even though it is deprecated starting from version 3" << endl; } record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PM, PM_LENGTH, (const unsigned char *)&settings.provisionMode); } // Provisioning Server Address (ver 2.1, 3 and 4) if (settings.provisionServerAddPresent) { // IPv4 supported in ver 2.1, 3 and 4 while IPv6 supported in ver 3 and 4 only; // Therefore, add the provision server address to the file only if it stands in the described terms. if ((IPV4 == settings.provisionServerAddType) || ((IPV6 == settings.provisionServerAddType) && (3 <= settings.majorVersion))) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PSADDR, settings.provisionServerAddSize, (const unsigned char *)settings.provisionServerAdd); } } // Provisioning Server Port (ver 2.1, 3 and 4) if (settings.provisionServerPortPresent) { // IPv4 supported in ver 2.1, 3 and 4 while IPv6 supported in ver 3 and 4 only; // Therefore, add the provision server port to the file only if it stands in the described terms. // (This check prevent from the user to add only the provision server port, // in case ipv6 address was given in ver 2.1) if ((IPV4 == settings.provisionServerAddType) || ((IPV6 == settings.provisionServerAddType) && (3 <= settings.majorVersion))) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PSPO, PROSERPORT_SIZE, (const unsigned char *)settings.provisionServerPort); } } // Static IPv4 Parameters (ver 2.1, 3 and 4) if (settings.staticIPv4ParamsPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_STATIC_PV4_PARAMS, STATIC_PV4_PARAMS_SIZE, (const unsigned char *)settings.staticIPv4Params); } // VLAN (ver 2.1, 3 and 4) if (settings.vlanPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_VLAN, VLAN_SIZE, (const unsigned char *)settings.vlan); } // MEBx Password Change Policy (ver 2.1, 3 and 4) if(settings.passPolicyFlagExist) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PASS_POLICY_FLAG, PASS_POLICY_FLAG_SIZE, (const unsigned char *)&settings.passPolicyFlag); } } if(3 <= settings.majorVersion) { // IPV6 (from ver 3 only) if (settings.ipv6ParamsPresent) { if(4 <= settings.majorVersion) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_IPV6, CM_VARIABLE_IDENTIFIER_IPV6_LEN_NEW_FORMAT, (const unsigned char *)settings.ipv6Params); } else { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_IPV6, CM_VARIABLE_IDENTIFIER_IPV6_LEN, (const unsigned char *)settings.ipv6Params); } } // Shared/Dedicated FQDN (from ver 3 only) if(settings.sharedDedicatedFqdnPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SHARED_DEDICATED_FQDN, CM_VARIABLE_IDENTIFIER_SHARED_DEDICATED_FQDN_LEN, (const unsigned char *)&settings.sharedDedicatedFqdn); } // Dynamic DNS Update (from ver 3 only) if(settings.dynamicDnsUpdatePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_DYNAMIC_DNS_UPDATE, CM_VARIABLE_IDENTIFIER_DYNAMIC_DNS_UPDATE_LEN, (const unsigned char *)&settings.dynamicDnsUpdate); } // KVM State (from ver 3 only) if(settings.kvmStatePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_KVM_STATE, CM_VARIABLE_IDENTIFIER_KVM_STATE_LEN, (const unsigned char *)&settings.kvmState); } // Opt-In user consent option (from ver 3 only) if(settings.optInUserConsentPresent) { //'all' (0xFF) option is supported starting from version 4 only if (settings.optInUserConsentOption != CM_VARIABLE_IDENTIFIER_OPT_IN_USER_CONSENT_ENABLE_ALL || settings.majorVersion == 4) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_OPT_IN_USER_CONSENT_OPTION, CM_VARIABLE_IDENTIFIER_OPT_IN_USER_CONSENT_OPTION_LEN, (const unsigned char *)&settings.optInUserConsentOption); } } // Opt-In remote IT consent policy (from ver 3 only) if(settings.optInRemoteITPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_OPT_IN_REMOTE_IT_CONSENT_POLICY, CM_VARIABLE_IDENTIFIER_OPT_IN_REMOTE_IT_CONSENT_POLICY_LEN, (const unsigned char *)&settings.optInRemoteItPolicy); } // ME provisioning Halt/Activate (from ver 3 only) if(settings.meProvisioningHaltActivatePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_ME_PROVISION_HALT_ACTIVE, CM_VARIABLE_IDENTIFIER_ME_PROVISION_HALT_ACTIVE_LEN, (const unsigned char *)&settings.meProvisioningHaltActivate); } // Manual Setup and Configuration (from ver 3 only) if(settings.manualSetupAndConfigurationPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_MANUAL_SETUP_AND_CONFIGURATION, CM_VARIABLE_IDENTIFIER_MANUAL_SETUP_AND_CONFIGURATION_LEN, (const unsigned char *)&settings.manualSetupAndConfiguration); } // Support Channel Identifier (from ver 3 only) if (settings.supportChannelIdentifierPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SUPPORT_CHANNEL_IDENTIFIER, CM_VARIABLE_IDENTIFIER_SUPPORT_CHANNEL_IDENTIFIER_LEN, (const unsigned char *)settings.supportChannelIdentifier); } // Support Channel Description (from ver 3 only) if (settings.supportChannelDescriptionPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SUPPORT_CHANNEL_DESCRIPTION, (unsigned short)settings.supportChannelDescription.length(), (const unsigned char *)settings.supportChannelDescription.c_str()); } // Service Account Number (from ver 3 only) if (settings.serviceAccountNumberPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SERVICE_ACCOUNT_NUMBER, (unsigned short)settings.serviceAccountNumber.length(), (const unsigned char *)settings.serviceAccountNumber.c_str()); } // Enrollment Passcode (from ver 3 only) if (settings.enrollmentPasscodePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_ENROLLMENT_PASSCODE, (unsigned short)settings.enrollmentPasscode.length(), (const unsigned char *)settings.enrollmentPasscode.c_str()); } // Service Type (from ver 3 only) if (settings.serviceTypePresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SERVICE_TYPE, CM_VARIABLE_IDENTIFIER_SERVICE_TYPE_LEN, (const unsigned char *)settings.serviceType); } // Service Provider Identifier (from ver 3 only) if (settings.serviceProviderIdentifierPresent) { record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_SERVICE_PROVIDER_IDENTIFIER, CM_VARIABLE_IDENTIFIER_SERVICE_PROVIDER_IDENTIFIER_LEN, (const unsigned char *)settings.serviceProviderIdentifier); } } if (4 == settings.majorVersion && settings.scrambleRecords) { record.SetScrambled(true); } /*********** End of Intel(R) AMT CM Variable Identifiers **********/ return CONFIG_SUCCESS; } int WriteConfigFile(const RecordSettings& settings, const string& fileName, bool overwrite, vector* cfgRecords) { if(!overwrite && MyFileExists(fileName)) { return CONFIG_FILE_WRITE_ERROR; } vector records; int retVal; DataRecord commonData; // default ctr // create data record adds all of the common fields retVal = CreateDataRecord(settings, commonData); if(retVal != CONFIG_SUCCESS) { return retVal; } for(int i = 0; i < settings.numRecords; i++) { DataRecord record(commonData); ConfigRecord cfgRecord; cfgRecord.valid = true; cfgRecord.hasPskPair = false; cfgRecord.CurrentMEBxPwd = settings.currentMEBxPwd; cfgRecord.NewMEBxPwd = settings.newMEBxPwd; if (!((settings.provisionModePresent)&&(CM_VARIABLE_IDENTIFIER_PM_SMB == settings.provisionMode))) { // make sure settings does not have pid\pps before generating if(settings.generateRandomPskPair && !settings.pidValid && !settings.ppsValid) { char pid[PID_LENGTH]; RandomPid(pid); char pps[PPS_LENGTH]; RandomPps(pps); record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PID, PID_LENGTH, (unsigned char*)pid); record.AddRecordEntry(MODULE_IDENTIFIER_AMT_CM, CM_VARIABLE_IDENTIFIER_PPS, PPS_LENGTH, (unsigned char*)pps); if (memcpy_s(&cfgRecord.Pid[0], ARRAYSIZE(cfgRecord.Pid), &pid[0], ARRAYSIZE(pid))) { return CONFIG_FILE_WRITE_ERROR; } if (memcpy_s(&cfgRecord.Pps[0], ARRAYSIZE(cfgRecord.Pps), &pps[0], ARRAYSIZE(pps))) { return CONFIG_FILE_WRITE_ERROR; } cfgRecord.hasPskPair = true; } else if (settings.pidValid && settings.ppsValid) { if (memcpy_s(&cfgRecord.Pid[0], ARRAYSIZE(cfgRecord.Pid), settings.pid, ARRAYSIZE(settings.pid))) { return CONFIG_FILE_WRITE_ERROR; } if (memcpy_s(&cfgRecord.Pps[0], ARRAYSIZE(cfgRecord.Pps), settings.pps, ARRAYSIZE(settings.pps))) { return CONFIG_FILE_WRITE_ERROR; } cfgRecord.hasPskPair = true; } } if(cfgRecords) { cfgRecords->push_back(cfgRecord); } records.push_back(record); } SetupFileInfo fileInfo; fileInfo.majorVersion = settings.majorVersion; switch(settings.majorVersion) { case SETUP_FILE_VERSION_1: fileInfo.minorVersion = 0; if (false == settings.multiple) { fileInfo.consumeRecords = true; } break; case SETUP_FILE_VERSION_2: fileInfo.minorVersion = settings.minorVersion; if (false == settings.multiple) { fileInfo.consumeRecords = settings.consumable; } break; case SETUP_FILE_VERSION_3: fileInfo.minorVersion = 0; if (false == settings.multiple) { fileInfo.consumeRecords = settings.consumable; } break; case SETUP_FILE_VERSION_4: fileInfo.minorVersion = 0; if (false == settings.multiple) { fileInfo.consumeRecords = settings.consumable; } break; default: return CONFIG_VERSION_UNSUPPORTED; } if (settings.multiple) { fileInfo.consumeRecords = true; } fileInfo.headerChunkCount = SINGLE_CHUNK_COUNT; fileInfo.recordCount = settings.numRecords; fileInfo.recordsConsumed = 0; // all records require the same chunk count fileInfo.dataRecordChunkCount = GetChunkCount(records[0]); unsigned int bufferLength = (unsigned int)CHUNK_SIZE * (fileInfo.headerChunkCount + records.size()*fileInfo.dataRecordChunkCount); unsigned char* data = new unsigned char[bufferLength]; memset(data, 0, bufferLength); retVal = RecordsToBuffer(records, fileInfo, bufferLength, data); if(retVal == CONFIG_SUCCESS) { ofstream setupFile(fileName.c_str(), ios_base::binary); if(!setupFile.is_open()) { retVal = CONFIG_FILE_WRITE_ERROR; } else { setupFile.write((char*)data,bufferLength); setupFile.close(); } } delete[] data; data = NULL; return retVal; } int ParseUsbFile(const string& fileName, SetupFileInfo* fileInfo, vector* records) { ifstream ifs(fileName.c_str(), ifstream::binary); if(!ifs.is_open()) { return CONFIG_FILE_READ_ERROR; } ifs.seekg(0,ifstream::end); unsigned int fileSize = ifs.tellg(); ifs.seekg(0); unsigned char* data = new unsigned char[fileSize]; ifs.read((char*)data, fileSize); ifs.close(); int retVal = BufferToRecords(fileSize, data, fileInfo, records); delete[] data; data = NULL; return retVal; } int DumpUsbFile(const string& fileName, ostream& out, bool printRecords) { SetupFileInfo info; info.majorVersion = 0; info.minorVersion = 0; info.consumeRecords = false; info.recordCount = 0; info.recordsConsumed = 0; vector records; int retVal = CONFIG_SUCCESS; if(CONFIG_SUCCESS != (retVal = ParseUsbFile(fileName, &info, &records))) { return retVal; } out << "USB file " << fileName.c_str() << " Contents:" << endl; out << "Setup File version = " << (unsigned int)info.majorVersion << "." << (unsigned int)info.minorVersion << endl; out << "Is Consumable = " << (info.consumeRecords ? "True" : "False") << endl; out << "Total Records = " << info.recordCount << endl; out << "Consumed Records = " << info.recordsConsumed << endl << endl; if(printRecords) { out << "Valid Records:" << endl; int recordValid; for(unsigned int i = 0; i < (unsigned int)records.size(); i++) { out << "Record " << info.recordsConsumed + i + 1 << ":" << endl; if(CONFIG_SUCCESS != (recordValid = PrintDataRecord(records[i], out, (unsigned int)info.majorVersion))) { out << "Illegal Record!!!" << endl; out << "The following error code was received while printing " "this record " << recordValid << endl; retVal = CONFIG_INVALID_RECORD; } out << endl; } } return retVal; } // print a pid void PrintPid(const unsigned char* pid, ostream& out) { for (int j=0; j<4; j++) { out << pid[j]; } out << "-"; for (int j=4; j<8; j++) { out << pid[j]; } } void PrintGuid(const unsigned char* guid, ostream& out) { out << hex; for (int i=0;i<16;i++) { if ((4==i) || (6==i) || (8==i) || (10==i)) out << "-"; if (i<4) out << setfill('0') << setw(2) <<(int)guid[3-i]; if ((i>=4)&&(i<=7)) { if (i%2==0) out << setfill('0') << setw(2) <<(int)guid[i+1]; else out << setfill('0') << setw(2) <<(int)guid[i-1]; } if (i>7) out << setfill('0') << setw(2) <<(int)guid[i]; } out< entries = record.GetRecordEntries(); for(unsigned int i = 0; i < (unsigned int) entries.size(); i++) { length = entries[i].GetVariableLength(); value = new unsigned char[length + 1]; entries[i].GetVariableValue(length, value); value[length] = 0; switch(entries[i].GetModuleId()) { case MODULE_IDENTIFIER_ME_KERNEL: switch(entries[i].GetVariableId()) { case ME_VARIABLE_IDENTIFIER_CURRENT_MEBX_PWD: if(length == 0 || length > MAX_PWD_LEN) { retVal = CONFIG_INVALID_CURR_PWD; break; } out << " Current MEBx password = " << value << endl; break; case ME_VARIABLE_IDENTIFIER_NEW_MEBX_PWD: if(length < MIN_PWD_LEN || length > MAX_PWD_LEN) { retVal = CONFIG_INVALID_NEW_PWD; break; } out << " New MEBx password = " << value << endl; break; case ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION: if(length != ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_LEN) { retVal = CONFIG_INVALID_MANAGEABILITY_FEATURE_SELECTION; break; } out << " Manageability mode = " << (unsigned short) value[0] < MAX_FRIENDLY_NAME_LENGTH) { ok = false; } if (!ok) { retVal = CONFIG_INVALID_CERT_SETTINGS; break; } out << " User Defined Certificate Hash = "; PrintCertHash(value + 1, *(value), out); out << endl; out << " Hash Algorithm = " << (unsigned short)(*value) << " (" << hashAlgorithmName << ")" << endl; out << " Friendly Name = " << value + friendlyNameIndex << endl; } break; case CM_VARIABLE_IDENTIFIER_SOL_IDE_REDIRECTION_CONFIG: if(length != CM_VARIABLE_IDENTIFIER_SOL_IDE_REDIRECTION_CONFIG_LEN) { retVal = CONFIG_INVALID_SOLIDER_CONFIG; break; } out << " SOL/IDE-R Config = " << (unsigned short)value[0] <