diff --git a/scripts/Capi2Probe.ps1 b/scripts/Capi2Probe.ps1 index aef959d4..b7651196 100644 --- a/scripts/Capi2Probe.ps1 +++ b/scripts/Capi2Probe.ps1 @@ -48,6 +48,7 @@ function Assert-WelaCapi2ProbeCertificate { if($der.Length -lt 128 -or $der.Length -gt 8192){throw 'Certificate DER exceeds its evidence bound.'} $certificate=[Security.Cryptography.X509Certificates.X509Certificate2]::new($der) try{ + if([Convert]::ToBase64String($certificate.RawData) -cne $Operation.CertificateDerBase64){throw 'Public certificate evidence must contain exactly one canonical DER object.'} if($certificate.Subject -cne ('CN=WelaCapi2Probe_'+$Nonce) -or $certificate.Issuer -cne $certificate.Subject -or $Operation.Subject -cne $certificate.Subject -or $Operation.Thumbprint -cne $certificate.Thumbprint -or $certificate.Extensions.Count -ne 0 -or $certificate.HasPrivateKey -or $certificate.SignatureAlgorithm.Value -cne '1.2.840.113549.1.1.11' -or $certificate.PublicKey.Oid.Value -cne '1.2.840.113549.1.1.1'){throw 'Certificate DER does not describe the fixed ephemeral self-signed probe.'} $rsa=[Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPublicKey($certificate) try{if($rsa.get_KeySize() -ne 2048){throw 'Unexpected probe RSA key size.'}}finally{$rsa.Dispose()} diff --git a/tests/Capi2Probe.Tests.ps1 b/tests/Capi2Probe.Tests.ps1 index bf2cce06..e9e136af 100644 --- a/tests/Capi2Probe.Tests.ps1 +++ b/tests/Capi2Probe.Tests.ps1 @@ -17,6 +17,7 @@ try{ $operation=[pscustomobject]@{Nonce=$nonce;CertificateDerBase64=[Convert]::ToBase64String($cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert));Subject=$cert.Subject;Thumbprint=$cert.Thumbprint;KeyEphemeral=$true;ProcessId=5678;ProcessName='pwsh.exe';StartedUtc=$now.AddSeconds(-1).ToString('o');CompletedUtc=$now.AddSeconds(1).ToString('o');Clock='GetSystemTimePreciseAsFileTime';RecordIdBefore=10;BeforeToken=$token;AfterToken=$token;Chain=[pscustomobject]@{Flags=2147492100;ErrorStatus=32;Chains=1;Elements=1}} $der=Assert-WelaCapi2ProbeCertificate $operation $nonce;Assert ($der.Length -gt 128) 'Generated test DER is validated.' }finally{if($cert){$cert.Dispose()};$rsa.Dispose()} +$bad=Clone $operation;$bad.CertificateDerBase64=[Convert]::ToBase64String(([byte[]]([Convert]::FromBase64String($operation.CertificateDerBase64)+[byte[]]@(0))));Reject {Assert-WelaCapi2ProbeCertificate $bad $nonce} 'Reject trailing data after the actual certificate DER.' foreach($field in @('Nonce','Subject','Thumbprint','CertificateDerBase64')){$bad=Clone $operation;$bad.$field='wrong';Reject {Assert-WelaCapi2ProbeCertificate $bad $nonce} "Reject certificate $field mismatch"} foreach($value in @($false,'true',$null)){$bad=Clone $operation;$bad.KeyEphemeral=$value;Reject {Assert-WelaCapi2ProbeCertificate $bad $nonce} 'Ephemeral key evidence must be true Boolean.'} foreach($field in @('Flags','ErrorStatus','Chains','Elements')){$bad=Clone $operation;$bad.Chain.$field=0;Reject {Assert-WelaCapi2ProbeCertificate $bad $nonce} "Reject unexpected native chain $field"}