Skip to content

Commit

Permalink
feat: ccm on new tls only platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
graikhel-intel committed Jan 15, 2025
1 parent 3916155 commit e367a9c
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 23 deletions.
Empty file modified build.sh
100755 → 100644
Empty file.
35 changes: 34 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ func runRPC(args []string) error {
if err != nil {
return err
}
// Update TLS enforcement and Current Activation Mode, helps decide how to connect to LMS
err = updateConnectionSettings(flags)
if err != nil {
return err
}
if flags.Local {
err = local.ExecuteCommand(flags)
} else {
Expand Down Expand Up @@ -85,6 +90,34 @@ func main() {
}
}

func updateConnectionSettings(flags *flags.Flags) error {
// Check if TLS is Mandatory for LMS connection
resp, err := flags.AmtCommand.GetChangeEnabled()
flags.LocalTlsEnforced = false
if err != nil {
if err.Error() == "wait timeout while sending data" {
log.Trace("Operation timed out while sending data. This may occur on systems with AMT version 11 and below.")
return nil
} else {
log.Error(err)
return err
}
}

if resp.IsTlsEnforcedOnLocalPorts() {
flags.LocalTlsEnforced = true
log.Trace("TLS is enforced on local ports")
}

// Check the current provisioning mode
flags.CurrentActivationMode, err = flags.AmtCommand.GetControlMode()
if err != nil {
return err
}

return nil
}

func handleErrorAndExit(err error) {
if customErr, ok := err.(utils.CustomError); ok {
if err != utils.HelpRequested {
Expand All @@ -95,4 +128,4 @@ func handleErrorAndExit(err error) {
log.Error(err.Error())
os.Exit(utils.GenericFailure.Code)
}
}
}
6 changes: 4 additions & 2 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ type Flags struct {
flagSetEnableWifiPort *flag.FlagSet
flagSetMEBx *flag.FlagSet
flagSetAMTFeatures *flag.FlagSet
amtCommand amt.AMTCommand
AmtCommand amt.AMTCommand
netEnumerator NetEnumerator
IpConfiguration IPConfiguration
HostnameInfo HostnameInfo
Expand All @@ -115,6 +115,8 @@ type Flags struct {
KVM bool
SOL bool
IDER bool
LocalTlsEnforced bool
CurrentActivationMode int
}

func NewFlags(args []string, pr utils.PasswordReader) *Flags {
Expand Down Expand Up @@ -142,7 +144,7 @@ func NewFlags(args []string, pr utils.PasswordReader) *Flags {
flags.flagSetMEBx = flag.NewFlagSet(utils.SubCommandSetMEBx, flag.ContinueOnError)
flags.flagSetAMTFeatures = flag.NewFlagSet(utils.SubCommandSetAMTFeatures, flag.ContinueOnError)

flags.amtCommand = amt.NewAMTCommand()
flags.AmtCommand = amt.NewAMTCommand()
flags.netEnumerator = NetEnumerator{}
flags.netEnumerator.Interfaces = net.Interfaces
flags.netEnumerator.InterfaceAddrs = (*net.Interface).Addrs
Expand Down
2 changes: 1 addition & 1 deletion internal/flags/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func (f *Flags) handleMaintenanceSyncIP() error {
return nil
}

amtLanIfc, err := f.amtCommand.GetLANInterfaceSettings(false)
amtLanIfc, err := f.AmtCommand.GetLANInterfaceSettings(false)
if err != nil {
log.Error(err)
return utils.AMTConnectionFailed
Expand Down
21 changes: 15 additions & 6 deletions internal/lm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package lm

import (
"crypto/tls"
"errors"
"io"
"net"
Expand All @@ -19,17 +20,21 @@ type LMSConnection struct {
Connection net.Conn
address string
port string
useTls bool
tlsConfig *tls.Config
data chan []byte
errors chan error
}

func NewLMSConnection(address string, port string, data chan []byte, errors chan error) *LMSConnection {
func NewLMSConnection(address string, port string, useTls bool, tlsConfig *tls.Config, data chan []byte, errors chan error) *LMSConnection {

lms := &LMSConnection{
address: address,
port: port,
data: data,
errors: errors,
address: address,
port: port,
useTls: useTls,
tlsConfig: tlsConfig,
data: data,
errors: errors,
}
return lms
}
Expand All @@ -42,7 +47,11 @@ func (lms *LMSConnection) Connect() error {
log.Debug("connecting to lms")
var err error
if lms.Connection == nil {
lms.Connection, err = net.Dial("tcp4", lms.address+":"+lms.port)
if lms.useTls {
lms.Connection, err = tls.Dial("tcp4", lms.address+":"+lms.port, lms.tlsConfig)
} else {
lms.Connection, err = net.Dial("tcp4", lms.address+":"+lms.port)
}
if err != nil {
// handle error
return err
Expand Down
8 changes: 5 additions & 3 deletions internal/local/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/hex"
Expand Down Expand Up @@ -38,9 +39,9 @@ func (service *ProvisioningService) Activate() error {
return err
}

tlsConfig := &tls.Config{}
if tlsEnforced {
log.Error("TLS is enforced on local ports, unable to activate")
return utils.UnsupportedAMTVersion
tlsConfig = utils.CreateTLSConfig(controlMode)
}

// for local activation, wsman client needs local system account credentials
Expand All @@ -49,7 +50,8 @@ func (service *ProvisioningService) Activate() error {
log.Error(err)
return utils.AMTConnectionFailed
}
service.interfacedWsmanMessage.SetupWsmanClient(lsa.Username, lsa.Password, log.GetLevel() == log.TraceLevel)

service.interfacedWsmanMessage.SetupWsmanClient(lsa.Username, lsa.Password, tlsEnforced, tlsConfig, log.GetLevel() == log.TraceLevel)

if service.flags.UseACM {
err = service.ActivateACM()
Expand Down
22 changes: 16 additions & 6 deletions internal/local/amt/wsman.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package amt

import (
tlsAlias "crypto/tls"
"encoding/base64"
"net"
"rpc/pkg/utils"
Expand Down Expand Up @@ -34,7 +35,7 @@ import (
)

type WSMANer interface {
SetupWsmanClient(username string, password string, logAMTMessages bool)
SetupWsmanClient(username string, password string, useTLS bool, tlsConfig *tlsAlias.Config, logAMTMessages bool)
Unprovision(int) (setupandconfiguration.Response, error)
GetGeneralSettings() (general.Response, error)
HostBasedSetupService(digestRealm string, password string) (hostbasedsetup.Response, error)
Expand Down Expand Up @@ -96,21 +97,30 @@ func NewGoWSMANMessages(lmsAddress string) *GoWSMANMessages {
}
}

func (g *GoWSMANMessages) SetupWsmanClient(username string, password string, logAMTMessages bool) {
func (g *GoWSMANMessages) SetupWsmanClient(username string, password string, useTLS bool, tlsConfig *tlsAlias.Config, logAMTMessages bool) {
clientParams := client.Parameters{
Target: g.target,
Username: username,
Password: password,
UseDigest: true,
UseTLS: false,
UseTLS: useTLS,
TlsConfig: tlsConfig,
LogAMTMessages: logAMTMessages,
}
logrus.Info("Attempting to connect to LMS...")
port := utils.LMSPort

var (
con net.Conn // Declared to hold the connection object
err error
)
if clientParams.UseTLS {
port = client.TLSPort
con, err = tlsAlias.Dial("tcp", utils.LMSAddress+":"+client.TLSPort, clientParams.TlsConfig)
} else {
con, err = net.Dial("tcp", utils.LMSAddress+":"+client.NonTLSPort)
logrus.Info("Successfully connected to LMS.")
con.Close()
}
con, err := net.Dial("tcp4", utils.LMSAddress+":"+port)

if err != nil {
logrus.Info("Failed to connect to LMS, using local transport instead.")
clientParams.Transport = NewLocalTransport()
Expand Down
3 changes: 2 additions & 1 deletion internal/local/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ func (service *ProvisioningService) Configure() (err error) {
log.Error("Device is not activated to configure. Please activate the device first.")
return utils.UnableToConfigure
}
service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, logrus.GetLevel() == logrus.TraceLevel)

service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, service.flags.LocalTlsEnforced, utils.CreateTLSConfig(controlMode), logrus.GetLevel() == logrus.TraceLevel)

switch service.flags.SubCommand {
case utils.SubCommandAddEthernetSettings, utils.SubCommandWired:
Expand Down
3 changes: 2 additions & 1 deletion internal/local/deactivate.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ func (service *ProvisioningService) DeactivateACM() (err error) {
return utils.MissingOrIncorrectPassword
}
}
service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, logrus.GetLevel() == logrus.TraceLevel)

service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, service.flags.LocalTlsEnforced, utils.CreateTLSConfig(service.flags.CurrentActivationMode), logrus.GetLevel() == logrus.TraceLevel)
_, err = service.interfacedWsmanMessage.Unprovision(1)
if err != nil {
log.Error("Status: Unable to deactivate ", err)
Expand Down
2 changes: 1 addition & 1 deletion internal/local/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ func (service *ProvisioningService) DisplayAMTInfo() (err error) {
}
}
if service.flags.AmtInfo.UserCert {
service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, logrus.GetLevel() == logrus.TraceLevel)
service.interfacedWsmanMessage.SetupWsmanClient("admin", service.flags.Password, service.flags.LocalTlsEnforced, utils.CreateTLSConfig(service.flags.CurrentActivationMode), logrus.GetLevel() == logrus.TraceLevel)
userCerts, _ := service.interfacedWsmanMessage.GetPublicKeyCerts()
userCertMap := map[string]publickey.RefinedPublicKeyCertificateResponse{}
for i := range userCerts {
Expand Down
10 changes: 9 additions & 1 deletion internal/rps/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package rps

import (
"crypto/tls"
"os"
"os/signal"
"rpc/internal/flags"
Expand All @@ -31,9 +32,16 @@ func NewExecutor(flags flags.Flags) (Executor, error) {
lmDataChannel := make(chan []byte)
lmErrorChannel := make(chan error)

port := utils.LMSPort
tlsConfig := &tls.Config{}
if flags.LocalTlsEnforced {
port = utils.LMSTLSPort
tlsConfig = utils.CreateTLSConfig(flags.CurrentActivationMode)
}

client := Executor{
server: NewAMTActivationServer(&flags),
localManagement: lm.NewLMSConnection(utils.LMSAddress, utils.LMSPort, lmDataChannel, lmErrorChannel),
localManagement: lm.NewLMSConnection(utils.LMSAddress, port, flags.LocalTlsEnforced, tlsConfig, lmDataChannel, lmErrorChannel),
data: lmDataChannel,
errors: lmErrorChannel,
waitGroup: &sync.WaitGroup{},
Expand Down
1 change: 1 addition & 0 deletions pkg/utils/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
LMSAddress = "localhost"
// LMSPort is used for determining what port to connect to LMS on
LMSPort = "16992"
LMSTLSPort = "16993"

AMTUserName = "admin"

Expand Down
85 changes: 85 additions & 0 deletions pkg/utils/tlsConfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package utils

import (
"crypto/x509"
"crypto/tls"
"strings"
log "github.com/sirupsen/logrus"
)

// CreateTLSConfig generates a TLS configuration based on the provided mode.
func CreateTLSConfig(currentMode int) *tls.Config {
if currentMode == 0 { // Pre-provisioning mode
return &tls.Config{
InsecureSkipVerify: true,
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
allowedLeafCNs := []string{
"AMT RCFG", "AMT AuditL", "AMT WS-MAN",
"iAMT CSME IDevID RCFG", "iAMT CSME IDevID AuditL", "iAMT CSME IDevID WS-MAN",
}

allowedPrefixes := []string{
"ODCA 2 CSME P", "ODCA 2 CSME", "On Die CSME", "On Die CSME P",
}

for i, rawCert := range rawCerts {
cert, err := x509.ParseCertificate(rawCert)
if err != nil {
log.Error("Failed to parse certificate", i, ":", err)
return err
}

if i == 0 { // Validate the leaf certificate
if !isAllowedLeafCN(cert.Subject.CommonName, allowedLeafCNs) {
log.Error("Leaf certificate CN is not allowed: ", cert.Subject.CommonName)
return err
}
}

if i == 3 { // Check the 4th certificate (CSME ROM ODCA Certificate)
if !strings.Contains(cert.Subject.CommonName, "ROM CA") {
log.Error("4th certificate Common Name does not contain 'ROM CA'")
return err
}

ouFound := false
for _, ou := range cert.Issuer.OrganizationalUnit {
for _, prefix := range allowedPrefixes {
if strings.Contains(ou, prefix) {
log.Trace("Valid 4th certificate Issuer OU: ", ou)
ouFound = true
break
}
}
if ouFound {
break
}
}

if !ouFound {
log.Error("4th certificate Issuer OU does not contain a valid prefix")
return err
}
}
}

return nil
},
}
}

// Default for ACM or CCM
log.Info("Setting default TLS Config for ACM/CCM mode")
return &tls.Config{
InsecureSkipVerify: true,
}
}

func isAllowedLeafCN(cn string, allowedCNs []string) bool {
for _, allowed := range allowedCNs {
if cn == allowed {
return true
}
}
return false
}

0 comments on commit e367a9c

Please sign in to comment.