499 lines
14 KiB
C#
499 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Security.Cryptography;
|
|
using System.Xml;
|
|
using Intel.Management.Wsman;
|
|
|
|
|
|
|
|
namespace Intel.Management.PSModule.Heci
|
|
{
|
|
|
|
public enum CertChainStatus
|
|
{
|
|
NotStarted = 0,
|
|
InProgress = 1,
|
|
Complete = 2,
|
|
}
|
|
|
|
public enum HashAlgorithmType
|
|
{
|
|
Unknown =0,
|
|
Sha1=1,
|
|
Sha256=2,
|
|
Sha384=3,
|
|
}
|
|
|
|
public class AmtSetupRecord
|
|
{
|
|
IManagedInstance _recordObj;
|
|
public AmtSetupRecord(IManagedInstance recordObj)
|
|
{
|
|
_recordObj = recordObj;
|
|
}
|
|
|
|
|
|
public DateTime Timestamp
|
|
{
|
|
get
|
|
{
|
|
return Amt.AmtDriveInfo.FormatDate(
|
|
_recordObj.GetProperty("CreationTimeStamp"));
|
|
}
|
|
}
|
|
|
|
|
|
public string LogName
|
|
{
|
|
get
|
|
{
|
|
return _recordObj.GetProperty("LogName").ToString();
|
|
}
|
|
}
|
|
|
|
public string RecordID
|
|
{
|
|
get
|
|
{
|
|
return _recordObj.GetProperty("RecordID").ToString();
|
|
}
|
|
}
|
|
|
|
|
|
public bool SecureDNS
|
|
{
|
|
get
|
|
{
|
|
if (_recordObj.GetProperty("SecureDNS").IsNull)
|
|
return false;
|
|
|
|
return bool.Parse(_recordObj.GetProperty("SecureDNS").ToString());
|
|
}
|
|
}
|
|
|
|
public string CertificateCN
|
|
{
|
|
get
|
|
{
|
|
if (_recordObj.GetProperty("CertificateCN").IsNull)
|
|
return string.Empty;
|
|
|
|
return
|
|
_recordObj.GetProperty("CertificateCN").ToString();
|
|
|
|
}
|
|
}
|
|
|
|
public HashAlgorithmType HashAlgorithm
|
|
{
|
|
get
|
|
{
|
|
if (!_recordObj.GetProperty("HashAlgorithm").IsNull)
|
|
{
|
|
return (HashAlgorithmType)int.Parse(_recordObj.GetProperty("HashAlgorithm").ToString());
|
|
}
|
|
else if (!_recordObj.GetProperty("SelectedHashType").IsNull)
|
|
{
|
|
return (HashAlgorithmType)int.Parse(_recordObj.GetProperty("SelectedHashType").ToString());
|
|
}
|
|
return HashAlgorithmType.Unknown;
|
|
}
|
|
}
|
|
|
|
|
|
public string CertificateHash
|
|
{
|
|
get
|
|
{
|
|
if (!_recordObj.GetProperty("ProvCertificateHash").IsNull)
|
|
{
|
|
return _recordObj.GetProperty("ProvCertificateHash").ToString();
|
|
}
|
|
else if (!_recordObj.GetProperty("SelectedHashData").IsNull)
|
|
{
|
|
return _recordObj.GetProperty("SelectedHashData").ToString();
|
|
}
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public string[] CaCertificateSerials
|
|
{
|
|
get
|
|
{
|
|
List<string> result = new List<string>();
|
|
foreach (IWsmanItem item in _recordObj.GetProperty("CaCertificateSerials"))
|
|
{
|
|
result.Add(item.ToString());
|
|
}
|
|
|
|
return result.ToArray();
|
|
}
|
|
}
|
|
|
|
public bool AdditionalCaSerialNums
|
|
{
|
|
get
|
|
{
|
|
if (_recordObj.GetProperty("AdditionalCaSerialNums").IsNull)
|
|
return false;
|
|
|
|
return bool.Parse(_recordObj.GetProperty("AdditionalCaSerialNums").ToString());
|
|
}
|
|
}
|
|
|
|
public bool HashIsOemDefault
|
|
{
|
|
get
|
|
{
|
|
if (_recordObj.GetProperty("HashIsOemDefault").IsNull)
|
|
return false;
|
|
|
|
return bool.Parse(_recordObj.GetProperty("HashIsOemDefault").ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
public class AmtSetupParameters
|
|
{
|
|
|
|
CertChainStatus _status;
|
|
X509Certificate2Collection _chain;
|
|
|
|
byte[] _mcNonce;
|
|
byte[] _configNonce;
|
|
byte[] _signature;
|
|
string _passwordHash;
|
|
IWsmanConnection _conn;
|
|
|
|
public AmtSetupParameters()
|
|
{
|
|
_status = CertChainStatus.NotStarted;
|
|
_chain = new X509Certificate2Collection();
|
|
|
|
}
|
|
|
|
public AmtSetupParameters(IWsmanConnection conn, CertChainStatus status)
|
|
{
|
|
_status = status;
|
|
_conn = conn;
|
|
_chain = new X509Certificate2Collection();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
_mcNonce = null;
|
|
_signature = null;
|
|
_passwordHash = null;
|
|
}
|
|
|
|
public CertChainStatus CertChainStatus
|
|
{
|
|
get { return _status; }
|
|
}
|
|
|
|
public string PasswordHash
|
|
{
|
|
get
|
|
{
|
|
return _passwordHash;
|
|
}
|
|
set
|
|
{
|
|
_passwordHash = null;
|
|
}
|
|
}
|
|
|
|
|
|
public void SetPassword(string password)
|
|
{
|
|
// get the realm from the connection
|
|
if (_conn == null)
|
|
throw new InvalidOperationException("Connection object not set");
|
|
|
|
IManagedInstance settingsObj = _conn.NewInstance("SELECT * FROM AMT_GeneralSettings");
|
|
string realm = settingsObj.GetProperty("DigestRealm").ToString();
|
|
SetPassword("admin", password, realm);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SetPassword(string admin, string password, string realm)
|
|
{
|
|
MD5 md5 = new MD5CryptoServiceProvider();
|
|
md5.Initialize();
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
builder.Append(admin);
|
|
builder.Append(":");
|
|
builder.Append(realm);
|
|
builder.Append(":");
|
|
builder.Append(password);
|
|
|
|
_passwordHash = BitConverter.ToString(md5.ComputeHash(Encoding.ASCII.GetBytes(builder.ToString())));
|
|
_passwordHash = _passwordHash.Replace("-", string.Empty);
|
|
}
|
|
|
|
|
|
X509Certificate2 FindIssuer(X509Certificate2 childCert)
|
|
{
|
|
//if the root is passed in return null
|
|
if (childCert.Subject.Equals(childCert.Issuer))
|
|
return null;
|
|
|
|
foreach (X509Certificate2 cert in _chain)
|
|
{
|
|
|
|
if (cert.Subject.Equals(childCert.Issuer))
|
|
return cert;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
public void SaveChain()
|
|
{
|
|
// get the realm from the connection
|
|
if (_conn == null)
|
|
throw new InvalidOperationException("Connection object not set");
|
|
|
|
|
|
IManagedReference refToService = _conn.NewReference("IPS_HostBasedSetupService");
|
|
refToService.AddSelector("Name", "Intel(r) AMT Host Based Setup Service");
|
|
IManagedInstance serviceObj = null;
|
|
|
|
//X509Certificate2Collection certs = new X509Certificate2Collection();
|
|
//certs.Import("C:\\Users\\amtadmin\\Documents\\Dev\\HBP\\setupchain.p7b");
|
|
|
|
List<string> issuers = new List<string>();
|
|
|
|
// loop throug the certs and find the root
|
|
foreach (X509Certificate2 cert in _chain)
|
|
{
|
|
issuers.Add(cert.Issuer);
|
|
}
|
|
|
|
List<X509Certificate2> certs = new List<X509Certificate2>();
|
|
X509Certificate2 nextCert = null;
|
|
// find leaf (is not an issuer of any cert)
|
|
foreach (X509Certificate2 cert in certs)
|
|
{
|
|
|
|
if (issuers.IndexOf(cert.Subject) < 0)
|
|
nextCert = cert;
|
|
}
|
|
|
|
while(nextCert !=null)
|
|
{
|
|
certs.Add(nextCert);
|
|
nextCert = FindIssuer(nextCert);
|
|
|
|
}
|
|
|
|
|
|
foreach (X509Certificate2 cert in certs)
|
|
{
|
|
while (_status!=CertChainStatus.Complete)
|
|
{
|
|
bool isLeaf = cert.Equals(certs.First());
|
|
bool isRoot = cert.Equals(certs.Last());
|
|
IManagedInstance inputObj = refToService.CreateMethodInput("AddNextCertInChain");
|
|
inputObj.SetProperty("NextCertificate", Convert.ToBase64String(cert.RawData));
|
|
inputObj.SetProperty("IsLeafCertificate", isLeaf.ToString().ToLower());
|
|
inputObj.SetProperty("IsRootCertificate", isRoot.ToString().ToLower());
|
|
IManagedInstance outObj = refToService.InvokeMethod(inputObj);
|
|
switch (outObj.GetProperty("ReturnValue").ToString())
|
|
{
|
|
case "0":
|
|
break;
|
|
case "1":
|
|
throw new ApplicationException("Invalid Parameter");
|
|
case "2":
|
|
throw new ApplicationException("Internal Error");
|
|
|
|
case "3":
|
|
|
|
throw new ApplicationException("Invalid State");
|
|
|
|
case "4":
|
|
throw new ApplicationException("Invalid certificate");
|
|
|
|
case "5":
|
|
//Chain length exceeded
|
|
throw new ApplicationException("chain length exceeded");
|
|
}
|
|
|
|
|
|
serviceObj = refToService.Get(); // refresh the service Object
|
|
_status=(CertChainStatus)int.Parse(serviceObj.GetProperty("CertChainStatus").ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
public byte[] ConfiguationNonce
|
|
{
|
|
get
|
|
{
|
|
return _configNonce;
|
|
}
|
|
set
|
|
{
|
|
_configNonce = value;
|
|
}
|
|
}
|
|
|
|
public byte[] McNonce
|
|
{
|
|
get
|
|
{
|
|
return _mcNonce;
|
|
}
|
|
set
|
|
{
|
|
_mcNonce = value;
|
|
}
|
|
}
|
|
|
|
public byte[] Signature
|
|
{
|
|
get
|
|
{
|
|
return _signature;
|
|
}
|
|
}
|
|
|
|
public string SignatureDescription
|
|
{
|
|
get { return "SHA256"; }
|
|
}
|
|
|
|
public byte[] Data
|
|
{
|
|
get
|
|
{
|
|
if (_configNonce == null)
|
|
throw new InvalidOperationException("No Configuration Nonce has been set");
|
|
|
|
if (_mcNonce == null)
|
|
throw new InvalidOperationException("No Mc Nonce has been set");
|
|
|
|
byte[] data = new byte[_configNonce.Length + _mcNonce.Length];
|
|
|
|
Array.Copy(_configNonce, 0, data, 0, _configNonce.Length);
|
|
Array.Copy(_mcNonce, 0, data, _configNonce.Length, _mcNonce.Length);
|
|
|
|
return data;
|
|
}
|
|
}
|
|
|
|
|
|
public void Import(string path)
|
|
{
|
|
_chain.Import(path);
|
|
}
|
|
|
|
public void ImportKey(string path, string password)
|
|
{
|
|
_chain.Import(path, password, X509KeyStorageFlags.Exportable);
|
|
}
|
|
|
|
string ToXmlString()
|
|
{
|
|
if (_mcNonce == null)
|
|
GenerateMcNonce();
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
builder.Append("<AmtSetupParameters>");
|
|
builder.Append("<McNonce>");
|
|
builder.Append(Convert.ToBase64String(_mcNonce));
|
|
builder.Append("</McNonce>");
|
|
builder.Append("<ConfigNonce>");
|
|
builder.Append(Convert.ToBase64String(_configNonce));
|
|
builder.Append("</ConfigNonce>");
|
|
builder.Append("</AmtSetupParameters>");
|
|
return builder.ToString();
|
|
}
|
|
|
|
public void FromXmlString(string xmlString)
|
|
{
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.LoadXml(xmlString);
|
|
}
|
|
|
|
|
|
|
|
public void GenerateMcNonce()
|
|
{
|
|
if (_mcNonce == null)
|
|
_mcNonce = new byte[20];
|
|
|
|
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
|
|
rng.GetBytes(_mcNonce);
|
|
}
|
|
|
|
public void SignData()
|
|
{
|
|
if (_mcNonce == null)
|
|
GenerateMcNonce();
|
|
|
|
SignData(Data);
|
|
}
|
|
|
|
public void SignData(byte[] data)
|
|
{
|
|
RSACryptoServiceProvider rsa=null;
|
|
|
|
//find the public key in the collection
|
|
foreach (X509Certificate2 cert in _chain)
|
|
{
|
|
if (cert.HasPrivateKey)
|
|
rsa = cert.PrivateKey as RSACryptoServiceProvider;
|
|
|
|
}
|
|
|
|
if (rsa == null)
|
|
throw new DriveException("Private key not found in certifcate chain");
|
|
|
|
RSAParameters rp = rsa.ExportParameters(true);
|
|
|
|
rsa = new RSACryptoServiceProvider();
|
|
rsa.ImportParameters(rp);
|
|
|
|
|
|
|
|
_signature = rsa.SignData(data, SignatureDescription);
|
|
if (!rsa.VerifyData(data, SignatureDescription, _signature))
|
|
{
|
|
throw new DriveException("RSA Signature not valid");
|
|
|
|
}
|
|
}
|
|
|
|
|
|
public X509Certificate2Collection Chain
|
|
{
|
|
get
|
|
{
|
|
return _chain;
|
|
}
|
|
set
|
|
{
|
|
_chain = value;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|