542 lines
20 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.Management.Automation;
using System.Management.Automation.Provider;
using Intel.Management.Wsman;
namespace Intel.Management.PSModule.Amt
{
class TLSService : DriveContainer
{
/// <summary>
/// Construcutor
/// </summary>
/// <param name="parent"></param>
public TLSService( DriveItem parent)
: base("TLS", parent)
{
}
public override void GetChildItems(ChildWriter writer)
{
IWsmanConnection conn = ((AmtRootService)GetRoot()).Connection;
IManagedReference refToLocal = conn.NewReference("AMT_TLSSettingData");
refToLocal.AddSelector("InstanceID", "Intel(r) AMT LMS TLS Settings");
IManagedReference refToRemote = conn.NewReference("AMT_TLSSettingData");
refToRemote.AddSelector("InstanceID", "Intel(r) AMT 802.3 TLS Settings");
writer.Add(new Certificates(this));
writer.Add(new Credential(this));
writer.Add(new TLSSettings("LocalSettings", refToLocal, this));
writer.Add(new TLSSettings("RemoteSettings",refToRemote, this));
writer.Add(new RsaKeys(this));
}
public static IManagedReference GetCertificateRef(DeviceCertificate devCert, IWsmanConnection conn)
{
IManagedReference refToCert = conn.NewReference("AMT_PublicKeyCertificate");
refToCert.AddSelector("InstanceID", devCert.InstanceID);
return refToCert;
}
public static IManagedReference GetTlsCertificate(string thumbprint, IWsmanConnection conn)
{
return Certificates.FindCertificate(thumbprint, conn);
}
public override object GetReturnObject()
{
return new NameValuePairItem(Name, Value);
}
/// <summary>
/// Embedded TLSSettings container
/// </summary>
class TLSSettings : SettingsContainer
{
public TLSSettings(string name, IManagedReference refToSettings, DriveItem parent)
: base(name, parent)
{
_refToSettings = refToSettings;
}
public override void GetChildItems(ChildWriter writer)
{
base.GetChildItems(writer);
if (HasSetting("AcceptNonSecureConnections"))
writer.Add(new BooleanSetting("AcceptNonSecureConnections", this));
writer.Add(new BooleanSetting("Enabled", this));
writer.Add(new BooleanSetting("MutualAuthentication", this));
writer.Add(new StringsSetting("TrustedCN", this));
}
}
/// <summary>
/// Contains all the private keys in the store
/// </summary>
public class RsaKeys : DriveContainer
{
public RsaKeys(DriveItem parent)
: base("RsaKeys", parent)
{
}
public override void GetChildItems(ChildWriter writer)
{
IWsmanConnection conn = ((AmtRootService)GetRoot()).Connection;
IWsmanEnumeration colObj = conn.ExecQuery("SELECT * FROM AMT_PublicPrivateKeyPair");
foreach (IWsmanItem item in colObj)
{
byte[] rawData = Convert.FromBase64String(item.Object.GetProperty("DERKey").ToString());
string name = item.Object.GetProperty("InstanceID").ToString();
writer.Add(new DriveEntry(name, Intel.Management.Mei.KeyFormatter.GetRSAKey(rawData), this));
}
}
public override object GetReturnObject()
{
return new NameValuePairItem(Name, Value);
}
}
class Credential : DriveContainer
{
public Credential(DriveContainer parent)
: base("Credentials", parent)
{
}
public override void GetChildItems(ChildWriter writer)
{
IWsmanConnection conn = ((AmtRootService)GetRoot()).Connection;
string thumbprint = string.Empty;
DeviceCertificate devCert = null;
foreach (IWsmanItem item in conn.ExecQuery("SELECT * FROM AMT_TLSCredentialContext"))
{
IManagedInstance certObj = item.Object.GetProperty("ElementInContext").Ref.Get();
devCert = new DeviceCertificate(certObj.GetProperty("X509Certificate").ToString(),
certObj.GetProperty("InstanceID").ToString(), false);
}
if (devCert == null)
devCert = new DeviceCertificate();
writer.Add(new ServerCertificate(devCert, this));
}
public override object GetReturnObject()
{
return new NameValuePairItem(Name, Value);
}
}
class ServerCertificate : DriveEntry
{
public ServerCertificate(DeviceCertificate devCert, DriveItem parent)
: base("ServerCertificate", devCert, parent)
{
}
public override void SetItem(object values, DriveProvider provider)
{
IWsmanConnection conn = ((AmtRootService)GetRoot()).Connection;
//look for exising TLS Credential
IManagedReference refToContext = Certificates.FindTlsCredential(conn);
if (values == null && refToContext != null)
{
refToContext.Delete();
_value = new DeviceCertificate();
}
else if (values is DeviceCertificate)
{
IManagedReference refToCertificate = GetCertificateRef((DeviceCertificate)values, conn);
// no existing reference
if (refToContext == null)
{
provider.WriteVerbose("No existing TLS Credential found so creating one.");
IManagedReference refToCollection = conn.NewReference("AMT_TLSProtocolEndpointCollection");
refToCollection.AddSelector("ElementName", "TLSProtocolEndpoint Instances Collection");
IManagedInstance credObj = conn.NewInstance("AMT_TLSCredentialContext");
credObj.SetProperty("ElementInContext", refToCertificate);
credObj.SetProperty("ElementProvidingContext", refToCollection);
credObj.Create();
_value = (DeviceCertificate)values;
}
else
{
provider.WriteVerbose("Updating exisiting TLS Certificate");
IManagedInstance credObj = refToContext.Get();
credObj.SetProperty("ElementInContext", refToCertificate);
refToContext.Put(credObj);
_value = (DeviceCertificate)values;
}
}
else
{
throw new System.Management.Automation.PSArgumentException("Value must be of type DeviceCertificate");
}
} //end set item
}// end ServerCertificate
class CertificateDriveItem : DriveItem
{
string[] _properties;
public override string[] Properties
{
get
{
return _properties;
}
}
public CertificateDriveItem(DeviceCertificate cert, DriveItem parent)
: base(cert.Thumbprint, cert, parent)
{
_properties = new string[2];
_properties[0] = "TrustedRootCertificate";
_properties[1] = "InstanceID";
}
public override void RemoveItem(DriveProvider provider)
{
IWsmanConnection conn = ((AmtRootService)GetRoot()).Connection;
IManagedReference refToCert = conn.NewReference("AMT_PublicKeyCertificate");
refToCert.AddSelector("InstanceID", InstanceID);
refToCert.Delete();
_parent.RemoveChildItem(this);
}
public string InstanceID
{
get { return ((DeviceCertificate)_value).InstanceID; }
}
public bool TrustedRootCertificate
{
get { return ((DeviceCertificate)_value).IsTrustedRootCertificate; }
}
public override object GetReturnObject()
{
return new CertificateItem(_value as DeviceCertificate);
}
}
/// <summary>
/// Contains all certificates in the store
/// </summary>
class Certificates : DriveContainer
{
public Certificates(DriveItem parent)
: base("Certificates", parent)
{
}
public override void GetChildItems(ChildWriter writer)
{
IWsmanConnection conn = ((AmtRootService)GetRoot()).Connection;
IWsmanEnumeration colObj = conn.ExecQuery("SELECT * FROM AMT_PublicKeyCertificate");
foreach (IWsmanItem item in colObj)
{
//byte[] rawData = Convert.FromBase64String(item.Object.GetProperty("X509Certificate").ToString());
//X509Certificate2 cert = new X509Certificate2(rawData);
DeviceCertificate cert = new DeviceCertificate(
item.Object.GetProperty("X509Certificate").ToString(),
item.Object.GetProperty("InstanceID").ToString(),
bool.Parse(item.Object.GetProperty("TrustedRootCertficate").ToString()));
writer.Add(new CertificateDriveItem(cert, this));
}
}
public override DriveItem NewItem(string name, string type, object newItem, DriveProvider provider)
{
IWsmanConnection conn = ((AmtRootService)GetRoot()).Connection;
if (type == null)
type = "Certificate";
if (string.Compare(type, "Certificate", true) == 0 ||
string.Compare(type, "TrustedRootCertificate", true) == 0 )
{
}
else
{
}
X509Certificate2 cert = null;
if (newItem is PSObject)
{
cert = (X509Certificate2)((PSObject)newItem).BaseObject;
}
else if (newItem is X509Certificate)
{
cert = (X509Certificate2)newItem;
}
if (cert==null)
throw new PSArgumentException("Only X509 Certificates can be created in this container");
IManagedReference refToService = conn.NewReference("SELECT * FROM AMT_PublicKeyManagementService");
IManagedReference refToCertificate = AddCertificate(cert, type, refToService, false);
IManagedInstance certObj = refToCertificate.Get();
if (string.Compare(type, "TrustedRootCertificate", true) != 0)
AddCertificateKey(cert, refToService);
bool trusted = bool.Parse(certObj.GetProperty("TrustedRootCertficate").ToString());
string instanceId = certObj.GetProperty("InstanceID").ToString();
DeviceCertificate firmCert = new DeviceCertificate(cert, instanceId, trusted);
CertificateDriveItem result= new CertificateDriveItem(firmCert, this);
AddChildItem(result);
return result;
}
public static IManagedReference FindCertificate(string thumbprint, IWsmanConnection conn)
{
IManagedReference result = null;
IWsmanEnumeration colObj = conn.ExecQuery("SELECT * FROM AMT_PublicKeyCertificate");
foreach (IWsmanItem item in colObj)
{
byte[] rawData = Convert.FromBase64String(item.Object.GetProperty("X509Certificate").ToString());
X509Certificate2 cert2 = new X509Certificate2(rawData);
if (string.Compare(cert2.Thumbprint, thumbprint, true) == 0)
{
result = conn.NewReference(item.Object.ResourceUri);
result.AddSelector("InstanceID", item.Object.GetProperty("InstanceID").ToString());
}
}
return result;
}
/* public static string GetTlsThumbrint(IWsmanConnection conn)
{
//look for exising TLS Credential
String result = string.Empty;
foreach (IWsmanItem item in conn.ExecQuery("SELECT * FROM AMT_TLSCredentialContext"))
{
IManagedInstance certObj = item.Object.GetProperty("ElementInContext").Ref.Get();
byte[] rawData = Convert.FromBase64String(certObj.GetProperty("X509Certificate").ToString());
X509Certificate2 cert2 = new X509Certificate2(rawData);
result = cert2.Thumbprint;
}
return result;
}*/
public static IManagedReference FindTlsCredential(IWsmanConnection conn)
{
//look for exising TLS Credential
IManagedReference refToContext = null;
foreach (IWsmanItem item in conn.ExecQuery("SELECT * FROM AMT_TLSCredentialContext"))
{
refToContext = conn.NewReference("AMT_TLSCredentialContext");
refToContext.AddSelector("ElementProvidingContext", item.Object.GetProperty("ElementProvidingContext").Ref);
refToContext.AddSelector("ElementInContext", item.Object.GetProperty("ElementInContext").Ref);
}
return refToContext;
}
public static IManagedReference FindCertificate(X509Certificate2 cert, IWsmanConnection conn)
{
IManagedReference result = null;
IWsmanEnumeration colObj = conn.ExecQuery("SELECT * FROM AMT_PublicKeyCertificate");
foreach (IWsmanItem item in colObj)
{
byte[] rawData = Convert.FromBase64String(item.Object.GetProperty("X509Certificate").ToString());
X509Certificate2 cert2 = new X509Certificate2(rawData);
if (string.Compare(cert2.Thumbprint, cert.Thumbprint, true) == 0)
{
result = conn.NewReference(item.Object.ResourceUri);
result.AddSelector("InstanceID", item.Object.GetProperty("InstanceID").ToString());
}
}
return result;
}
public static IManagedReference AddCertificate(X509Certificate2 cert, string type, IManagedReference refToService, bool allowDuplicate)
{
IManagedReference result = null;
IManagedInstance inputObj = null;
if (string.Compare(type, "trustedrootcertificate", true) == 0)
{
inputObj = refToService.CreateMethodInput("AddTrustedRootCertificate");
}
else
{
inputObj = refToService.CreateMethodInput("AddCertificate");
}
inputObj.SetProperty("CertificateBlob", Convert.ToBase64String(cert.RawData));
IManagedInstance outObj = refToService.InvokeMethod(inputObj);
switch (outObj.GetProperty("ReturnValue").ToString())
{
case "0":
result = outObj.GetProperty("CreatedCertificate").Ref;
break;
case "1":
AmtException.ThrowInvokeError(outObj, "Internal Error");
break;
case "16":
AmtException.ThrowInvokeError(outObj, "Not Permitted");
break;
case "23":
AmtException.ThrowInvokeError(outObj, "Certificate Max Limit Reached");
break;
case "38":
AmtException.ThrowInvokeError(outObj, "Flash write limit reached");
break;
case "2058":
if (allowDuplicate)
result = FindCertificate(cert, refToService.Connection);
else
AmtException.ThrowInvokeError(outObj, "Duplicate Certificate");
break;
case "2063":
AmtException.ThrowInvokeError(outObj, "Invalid Certificate");
break;
default:
throw new WsmanInvokeException("AMT error " + outObj.GetProperty("ReturnValue").ToString());
}
return result;
}
public static void AddCertificateKey(X509Certificate2 cert, IManagedReference refToService)
{
byte[] keyData = null;
if (cert.HasPrivateKey)
{
if (cert.PrivateKey is RSACryptoServiceProvider)
{
keyData = Intel.Management.Mei.KeyFormatter.EncodeKey(cert.PrivateKey as RSACryptoServiceProvider, true);
}
}
if (keyData != null)
{
IManagedInstance inputObj = refToService.CreateMethodInput("AddKey");
inputObj.SetProperty("KeyBlob", Convert.ToBase64String(keyData));
IManagedInstance outObj = refToService.InvokeMethod(inputObj);
switch (outObj.GetProperty("ReturnValue").ToString())
{
case "0":
break;
case "1":
AmtException.ThrowInvokeError(outObj, "Internal Error");
break;
case "23":
AmtException.ThrowInvokeError(outObj, "Key Max Limit Reached");
break;
case "38":
AmtException.ThrowInvokeError(outObj, "Flash write limit reached");
break;
case "2058":
break;
case "2062":
AmtException.ThrowInvokeError(outObj, "Invalid Key");
break;
default:
throw new WsmanInvokeException("AMT error " + outObj.GetProperty("ReturnValue").ToString());
}
}
}
public override object GetReturnObject()
{
return new NameValuePairItem(Name, Value);
}
}
}// end TLS Service
}//end namespace