WDACSimulation/Get-CertificateDetails.psm1
Function Get-CertificateDetails { <# .SYNOPSIS A function to detect Root, Intermediate and Leaf certificates It returns a compound object that contains 2 nested objects for Intermediate and Leaf certificates .INPUTS WDACConfig.AllCertificatesGrabber.AllFileSigners[] .OUTPUTS WDACConfig.ChainPackage[] .PARAMETER CompleteSignatureResult .NOTES Old method of recognizing the certificate type: If the file's subject common name is equal to the certificate's subject common name, then it's the leaf certificate - If a certificate's subject common name is equal to its issuer common name, then it's a root certificate - otherwise it's an intermediate certificate CertType = ($SubjectCN -eq $IssuerCN) ? 'Root' : (($SubjectCN -eq $FileSubjectCN) ? 'Leaf' : 'Intermediate') #> [CmdletBinding()] [OutputType([WDACConfig.ChainPackage[]])] param ( [Parameter(Mandatory = $true)][WDACConfig.AllCertificatesGrabber.AllFileSigners[]]$CompleteSignatureResult ) Begin { [System.Boolean]$Verbose = $PSBoundParameters.Verbose.IsPresent ? $true : $false . "$([WDACConfig.GlobalVars]::ModuleRootPath)\CoreExt\PSDefaultParameterValues.ps1" $FinalObject = New-Object -TypeName System.Collections.Generic.List[WDACConfig.ChainPackage] } process { # Loop over each signer of the file, in case the file has multiple separate signers for ($i = 0; $i -lt $CompleteSignatureResult.Count; $i++) { # Get the current chain and SignedCms of the signer [System.Security.Cryptography.X509Certificates.X509Chain]$CurrentChain = $CompleteSignatureResult.Chain[$i] [System.Security.Cryptography.Pkcs.SignedCms]$CurrentSignedCms = $CompleteSignatureResult.Signer[$i] [System.UInt32]$CertificatesInChainCount = $CurrentChain.ChainElements.Certificate.Count :ChainProcessLoop Switch ($CertificatesInChainCount) { # If the chain includes a Root, Leaf and at least one Intermediate certificate { $_ -gt 2 } { # The last certificate in the chain is the Root certificate [System.Security.Cryptography.X509Certificates.X509Certificate]$CurrentRootCertificate = $CurrentChain.ChainElements.Certificate[-1] $RootCertificate = [WDACConfig.ChainElement]::New( [WDACConfig.CryptoAPI]::GetNameString($CurrentRootCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $false), # SubjectCN [WDACConfig.CryptoAPI]::GetNameString($CurrentRootCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $true), # IssuerCN $CurrentRootCertificate.NotAfter, [WDACConfig.CertificateHelper]::GetTBSCertificate($CurrentRootCertificate), $CurrentRootCertificate, # Append the certificate object itself to the output object as well [WDACConfig.CertificateType]::Root ) # An array to hold the Intermediate Certificate(s) of the current chain $IntermediateCertificates = New-Object -TypeName System.Collections.Generic.List[WDACConfig.ChainElement] # All the certificates in between are Intermediate certificates foreach ($Cert in $CurrentChain.ChainElements.Certificate[1..($CertificatesInChainCount - 2)]) { # Create a collection of intermediate certificates $IntermediateCertificates.Add([WDACConfig.ChainElement]::New( [WDACConfig.CryptoAPI]::GetNameString($Cert.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $false), [WDACConfig.CryptoAPI]::GetNameString($Cert.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $true), $Cert.NotAfter, [WDACConfig.CertificateHelper]::GetTBSCertificate($Cert) , $Cert, # Append the certificate object itself to the output object as well [WDACConfig.CertificateType]::Intermediate )) } # The first certificate in the chain is the Leaf certificate [System.Security.Cryptography.X509Certificates.X509Certificate]$CurrentLeafCertificate = $CurrentChain.ChainElements.Certificate[0] $LeafCertificate = [WDACConfig.ChainElement]::New( [WDACConfig.CryptoAPI]::GetNameString($CurrentLeafCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $false), [WDACConfig.CryptoAPI]::GetNameString($CurrentLeafCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $true), $CurrentLeafCertificate.NotAfter, [WDACConfig.CertificateHelper]::GetTBSCertificate($CurrentLeafCertificate), $CurrentLeafCertificate, # Append the certificate object itself to the output object as well [WDACConfig.CertificateType]::Leaf ) $FinalObject.Add([WDACConfig.ChainPackage]::New( $CurrentChain, # The entire current chain of the certificate $CurrentSignedCms, # The entire current SignedCms object $RootCertificate, $IntermediateCertificates, $LeafCertificate )) Break ChainProcessLoop } # If the chain only includes a Root and Leaf certificate { $_ -eq 2 } { # The last certificate in the chain is the Root certificate [System.Security.Cryptography.X509Certificates.X509Certificate]$CurrentRootCertificate = $CurrentChain.ChainElements.Certificate[-1] $RootCertificate = [WDACConfig.ChainElement]::New( [WDACConfig.CryptoAPI]::GetNameString($CurrentRootCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $false), # SubjectCN [WDACConfig.CryptoAPI]::GetNameString($CurrentRootCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $true), # IssuerCN $CurrentRootCertificate.NotAfter, [WDACConfig.CertificateHelper]::GetTBSCertificate($CurrentRootCertificate), $CurrentRootCertificate, # Append the certificate object itself to the output object as well [WDACConfig.CertificateType]::Root ) # The first certificate in the chain is the Leaf certificate [System.Security.Cryptography.X509Certificates.X509Certificate]$CurrentLeafCertificate = $CurrentChain.ChainElements.Certificate[0] $LeafCertificate = [WDACConfig.ChainElement]::New( [WDACConfig.CryptoAPI]::GetNameString($CurrentLeafCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $false), [WDACConfig.CryptoAPI]::GetNameString($CurrentLeafCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $true), $CurrentLeafCertificate.NotAfter, [WDACConfig.CertificateHelper]::GetTBSCertificate($CurrentLeafCertificate), $CurrentLeafCertificate, # Append the certificate object itself to the output object as well [WDACConfig.CertificateType]::Leaf ) $FinalObject.Add([WDACConfig.ChainPackage]::New( $CurrentChain, # The entire current chain of the certificate $CurrentSignedCms, # The entire current SignedCms object $RootCertificate, $null, $LeafCertificate )) break ChainProcessLoop } # If the chain only includes a Root certificate { $_ -eq 1 } { # The only certificate in the chain is the Root certificate [System.Security.Cryptography.X509Certificates.X509Certificate]$CurrentRootCertificate = $CurrentChain.ChainElements.Certificate $RootCertificate = [WDACConfig.ChainElement]::New( [WDACConfig.CryptoAPI]::GetNameString($CurrentRootCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $false), # SubjectCN [WDACConfig.CryptoAPI]::GetNameString($CurrentRootCertificate.Handle, [WDACConfig.CryptoAPI]::CERT_NAME_SIMPLE_DISPLAY_TYPE, $null, $true), # IssuerCN $CurrentRootCertificate.NotAfter, [WDACConfig.CertificateHelper]::GetTBSCertificate($CurrentRootCertificate), $CurrentRootCertificate, # Append the certificate object itself to the output object as well [WDACConfig.CertificateType]::Root ) $FinalObject.Add([WDACConfig.ChainPackage]::New( $CurrentChain, # The entire current chain of the certificate $CurrentSignedCms, # The entire current SignedCms object $RootCertificate, $null, $null )) break ChainProcessLoop } } } } End { return $FinalObject } } Export-ModuleMember -Function 'Get-CertificateDetails' |