Skip to content

Commit

Permalink
refactor: adds more specific log errors for amt activation (#569)
Browse files Browse the repository at this point in the history
  • Loading branch information
Craig-Spencer-12 authored Jul 2, 2024
1 parent cf71b80 commit 9cb1261
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 27 deletions.
56 changes: 30 additions & 26 deletions internal/local/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (service *ProvisioningService) Activate() error {

controlMode, err := service.amtCommand.GetControlMode()
if err != nil {
return utils.AMTConnectionFailed
return utils.ActivationFailedGetControlMode
}
if controlMode != 0 {
log.Error("Device is already activated")
Expand Down Expand Up @@ -60,52 +60,52 @@ func (service *ProvisioningService) ActivateACM() error {
// Extract the provisioning certificate
certObject, fingerPrint, err := service.GetProvisioningCertObj()
if err != nil {
return utils.ActivationFailed
return err
}
// Check provisioning certificate is accepted by AMT
err = service.CompareCertHashes(fingerPrint)
if err != nil {
return utils.ActivationFailed
return err
}

generalSettings, err := service.interfacedWsmanMessage.GetGeneralSettings()
if err != nil {
return utils.ActivationFailed
return utils.ActivationFailedGeneralSettings
}

getHostBasedSetupResponse, err := service.interfacedWsmanMessage.GetHostBasedSetupService()
if err != nil {
return utils.ActivationFailed
return utils.ActivationFailedSetupService
}
decodedNonce := getHostBasedSetupResponse.Body.GetResponse.ConfigurationNonce
fwNonce, err := base64.StdEncoding.DecodeString(decodedNonce)
if err != nil {
return utils.ActivationFailed
return utils.ActivationFailedDecode64
}

err = service.injectCertificate(certObject.certChain)
if err != nil {
return utils.ActivationFailed
return err
}

nonce, err := service.generateNonce()
if err != nil {
return utils.ActivationFailed
return err
}

signedSignature, err := service.createSignedString(nonce, fwNonce, certObject.privateKey)
if err != nil {
return utils.ActivationFailed
return err
}

_, err = service.interfacedWsmanMessage.HostBasedSetupServiceAdmin(service.config.ACMSettings.AMTPassword, generalSettings.Body.GetResponse.DigestRealm, nonce, signedSignature)
if err != nil {
controlMode, err := service.amtCommand.GetControlMode()
if err != nil {
return utils.AMTConnectionFailed
return utils.ActivationFailedGetControlMode
}
if controlMode != 2 {
return utils.ActivationFailed
return utils.ActivationFailedControlMode
}
return nil
}
Expand All @@ -115,11 +115,11 @@ func (service *ProvisioningService) ActivateACM() error {
func (service *ProvisioningService) ActivateCCM() error {
generalSettings, err := service.interfacedWsmanMessage.GetGeneralSettings()
if err != nil {
return utils.ActivationFailed
return utils.ActivationFailedGeneralSettings
}
_, err = service.interfacedWsmanMessage.HostBasedSetupService(generalSettings.Body.GetResponse.DigestRealm, service.config.Password)
if err != nil {
return utils.ActivationFailed
return utils.ActivationFailedSetupService
}
log.Info("Status: Device activated in Client Control Mode")
return nil
Expand Down Expand Up @@ -163,11 +163,15 @@ func (service *ProvisioningService) GetProvisioningCertObj() (ProvisioningCertOb
func convertPfxToObject(pfxb64 string, passphrase string) (CertsAndKeys, error) {
pfx, err := base64.StdEncoding.DecodeString(pfxb64)
if err != nil {
return CertsAndKeys{}, err
return CertsAndKeys{}, utils.ActivationFailedDecode64
}
privateKey, certificate, extraCerts, err := pkcs12.DecodeChain(pfx, passphrase)
if err != nil {
return CertsAndKeys{}, errors.New("decrypting provisioning certificate failed")
if strings.Contains(err.Error(), "decryption password incorrect") {
return CertsAndKeys{}, utils.ActivationFailedWrongCertPass
}

return CertsAndKeys{}, utils.ActivationFailedInvalidProvCert
}
certs := append([]*x509.Certificate{certificate}, extraCerts...)
pfxOut := CertsAndKeys{certs: certs, keys: []interface{}{privateKey}}
Expand All @@ -177,10 +181,10 @@ func convertPfxToObject(pfxb64 string, passphrase string) (CertsAndKeys, error)

func dumpPfx(pfxobj CertsAndKeys) (ProvisioningCertObj, string, error) {
if len(pfxobj.certs) == 0 {
return ProvisioningCertObj{}, "", errors.New("no certificates found")
return ProvisioningCertObj{}, "", utils.ActivationFailedNoCertFound
}
if len(pfxobj.keys) == 0 {
return ProvisioningCertObj{}, "", errors.New("no private keys found")
return ProvisioningCertObj{}, "", utils.ActivationFailedNoPrivKeys
}
var provisioningCertificateObj ProvisioningCertObj
var certificateList []*CertificateObject
Expand All @@ -206,6 +210,10 @@ func dumpPfx(pfxobj CertsAndKeys) (ProvisioningCertObj, string, error) {
certificateList = append(certificateList, &certificateObject)
}

if fingerprint == "" {
return provisioningCertificateObj, "", utils.ActivationFailedNoRootCertFound
}

// Order the certificates from leaf to root
orderedCertificateList := orderCertificates(certificateList)

Expand Down Expand Up @@ -254,14 +262,14 @@ func orderCertificates(certificates []*CertificateObject) []*CertificateObject {
func (service *ProvisioningService) CompareCertHashes(fingerPrint string) error {
result, err := service.amtCommand.GetCertificateHashes()
if err != nil {
log.Error(err)
return utils.ActivationFailedGetCertHash
}
for _, v := range result {
if v.Hash == fingerPrint {
return nil
}
}
return errors.New("the root of the provisioning certificate does not match any of the trusted roots in AMT")
return utils.ActivationFailedProvCertNoMatch
}

func (service *ProvisioningService) injectCertificate(certChain []string) error {
Expand All @@ -273,9 +281,7 @@ func (service *ProvisioningService) injectCertificate(certChain []string) error

_, err := service.interfacedWsmanMessage.AddNextCertInChain(cert, isLeaf, isRoot)
if err != nil {
log.Error(err)
// TODO: check if this is the correct error to return
return errors.New("failed to add certificate to AMT")
return utils.ActivationFailedAddCert
}
}
return nil
Expand All @@ -285,8 +291,7 @@ func (service *ProvisioningService) generateNonce() ([]byte, error) {
nonce := make([]byte, 20)
// fills nonce with 20 random bytes
if _, err := rand.Read(nonce); err != nil {
log.Error("Error generating nonce:", err)
return nil, err
return nil, utils.ActivationFailedGenerateNonce
}
return nonce, nil
}
Expand Down Expand Up @@ -327,8 +332,7 @@ func (service *ProvisioningService) createSignedString(nonce []byte, fwNonce []b
arr := append(fwNonce, nonce...)
signature, err := service.signString(arr, privateKey)
if err != nil {
log.Error("Error signing string:", err)
return "", err
return "", utils.ActivationFailedSignString
}
return signature, nil
}
15 changes: 15 additions & 0 deletions pkg/utils/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,21 @@ var MissingIeee8021xConfiguration = CustomError{Code: 117, Message: "MissingIeee
var SetMEBXPasswordFailed = CustomError{Code: 118, Message: "SetMEBXPasswordFailed"}
var ChangeAMTPasswordFailed = CustomError{Code: 119, Message: "ChangeAMTPasswordFailed"}
var UnableToConfigure = CustomError{Code: 120, Message: "UnableToConfigure"}
var ActivationFailedDecode64 = CustomError{Code: 121, Message: "ActivationFailed", Details: "failed to decode the certificate from Base64 format"}
var ActivationFailedWrongCertPass = CustomError{Code: 122, Message: "ActivationFailed", Details: "provisioning cert password incorrect"}
var ActivationFailedInvalidProvCert = CustomError{Code: 123, Message: "ActivationFailed", Details: "invalid provisioning certificate"}
var ActivationFailedNoCertFound = CustomError{Code: 124, Message: "ActivationFailed", Details: "no certificates found"}
var ActivationFailedNoPrivKeys = CustomError{Code: 125, Message: "ActivationFailed", Details: "no private keys found"}
var ActivationFailedNoRootCertFound = CustomError{Code: 126, Message: "ActivationFailed", Details: "root certificate not found in the pfx"}
var ActivationFailedGetCertHash = CustomError{Code: 127, Message: "ActivationFailed", Details: "failed to get certificate hashes"}
var ActivationFailedProvCertNoMatch = CustomError{Code: 128, Message: "ActivationFailed", Details: "the root of the provisioning certificate does not match any of the trusted roots in AMT"}
var ActivationFailedGeneralSettings = CustomError{Code: 129, Message: "ActivationFailed", Details: "wsman message error, failed to get general settings"}
var ActivationFailedSetupService = CustomError{Code: 130, Message: "ActivationFailed", Details: "wsman message error, failed to get host based setup service response"}
var ActivationFailedAddCert = CustomError{Code: 131, Message: "ActivationFailed", Details: "wsman message error, failed to add certificate to AMT"}
var ActivationFailedGenerateNonce = CustomError{Code: 132, Message: "ActivationFailed", Details: "failed to generate nonce"}
var ActivationFailedSignString = CustomError{Code: 133, Message: "ActivationFailed", Details: "failed to create signed string"}
var ActivationFailedGetControlMode = CustomError{Code: 134, Message: "ActivationFailed", Details: "failed to get control mode"}
var ActivationFailedControlMode = CustomError{Code: 135, Message: "ActivationFailed", Details: "recieved invalid control mode"}

// (150-199) Maintenance Errors
var SyncClockFailed = CustomError{Code: 150, Message: "SyncClockFailed"}
Expand Down
7 changes: 6 additions & 1 deletion pkg/utils/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ import "fmt"
type CustomError struct {
Code int
Message string
Details string
}

// Error implements the error interface for CustomError.
func (e CustomError) Error() string {
return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
if e.Details != "" {
return fmt.Sprintf("Error %d: %s - Details: %s", e.Code, e.Message, e.Details)
} else {
return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}
}

0 comments on commit 9cb1261

Please sign in to comment.