From 9cb1261112631095914f18cdd26f976c944f75b4 Mon Sep 17 00:00:00 2001 From: Craig Spencer Date: Tue, 2 Jul 2024 14:13:09 -0700 Subject: [PATCH] refactor: adds more specific log errors for amt activation (#569) --- internal/local/activate.go | 56 ++++++++++++++++++++------------------ pkg/utils/constants.go | 15 ++++++++++ pkg/utils/error.go | 7 ++++- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/internal/local/activate.go b/internal/local/activate.go index 36388349..87d168dc 100644 --- a/internal/local/activate.go +++ b/internal/local/activate.go @@ -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") @@ -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 } @@ -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 @@ -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}} @@ -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 @@ -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) @@ -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 { @@ -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 @@ -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 } @@ -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 } diff --git a/pkg/utils/constants.go b/pkg/utils/constants.go index 0c6b18e1..00382a70 100644 --- a/pkg/utils/constants.go +++ b/pkg/utils/constants.go @@ -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"} diff --git a/pkg/utils/error.go b/pkg/utils/error.go index ac745855..896e985d 100644 --- a/pkg/utils/error.go +++ b/pkg/utils/error.go @@ -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) + } }