WindowsAppSDK icon indicating copy to clipboard operation
WindowsAppSDK copied to clipboard

Certificate.BuildChainAsync fails with custom trust root

Open bjorn-malmo opened this issue 2 years ago • 3 comments

Describe the bug

Trying to validate a certificate which is issued by a known authority, that is not installed in the Trusted Root Store fails with COMException 'The operation attempted to access data outside the valid range (0x8000000B)'

This happens when the known issuer is added to the ExclusiveTrustRoots list of the ChainBuildingParameters object.

Steps to reproduce the bug

  1. Create a project targeting .NET 7 and call the VerifyCertificate method as specified below
  2. The exception will be thrown .
  3. If the line builderParams.ExclusiveTrustRoots.Add(issuerCert); is removed, it will successfully validate the certificate, but of course with a result of Untrusted.

` public static async Task VerifyCertificate() { var childBlob = System.Convert.FromBase64String("MIIGnDCCBISgAwIBAgIgPwMuy88XYxNRrVLrQRKUi3MC+84jEbwfnBt2USZO+24wDQYJKoZIhvcNAQELBQAwUzEjMCEGA1UEAxMaVmlkaVZpZXcgTGljZW5zZSBBdXRob3JpdHkxHzAdBgNVBAoTFkRpc3RyaWJ1dGVkIE1lZGljYWwgQUIxCzAJBgNVBAYTAlNFMB4XDTIzMDQwNDIyMDAwMFoXDTI0MDEzMDIzMDAwMFowLDEbMBkGA1UEAxMSVmlkaVZpZXcgUjQgU2VydmVyMQ0wCwYDVQQKEwRETUFCMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp9+i54jDM/dNOaEBnOi5jn5HA5ItXXHFrsNDSkSEK71K+D+mqDDZAN7LG+KQ1Vi/OUipDheO5DLuU/xLdW2L7I1/khzUnfY6dmbQr/fOQQyOh3gcLJtTZm8xhYiQwQIbSnLnPb4fJskKftzesXv6qmtDhDlhr7vh20eH4qSADaQYOXV5DKmUxy8Vf1Nzppe6dncOJLqZT+XT0VPyIwdzPynNnd9x0JiPMPky4DiAIxdm6C3ZZQDVtQIyJ+bi49bkLybRBfmS/hWwCHUU7ySUMkZKSb6Devg3GH7n+29y7OoGFfxK5lEASNEVTrlX+bdjmbx02mS5+Sw/0ag3skdiZOjBW7In4jig4j8NPdKuTapBC60yVYNPQlb+ouJxiGij6/C8fZ9h5dnVonepJy2x1qTHEe6oF0XApAdVEPZHjGqA5bfCKH7Tb3p3W/vwNVH5KxF2XM6IFTIbvqVTcpCY/aMFRtXuZMrDnzB7E/XNKU60gwXwp0LfR1IaXToJ8fnWXJorC0dISKqgbQN6vI2ESBC16eUhg+PC8B3hyyGNws4hPpffVdwq1JwpCsiOq/8c5UqW/ZeG03lnQsTxk6Icrlns3V+yyHGTunjvqV6KFHEkkZJnOUdd5IP85fDBmZO8iMMOmeEz1oP1QZt5A1wimwTai6SgbSw8Ich8Uc3SvuUCAwEAAaOCAYEwggF9MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgOIMBsGCSsGAQQBgeQsAQQOVmlkaVZpZXdTZXJ2ZXIwDgYJKwYBBAGB5CwCBAEqMDkGCSsGAQQBgeQsAwQseGpMbDBmd2t5VzJ4QmMyQ29Gclh5cGZ4WG9MTmZiNHBaVXZaNlVYV0FiTT0wDgYKKwYBBAGB5CwDAgQAMBcGCSsGAQQBgeQsBAQKMTY4MDk2ODc0ODAgBgkrBgEEAYHkLAUEE0Rpc3RyaWJ1dGVkIE1lZGljYWwwDQYJKwYBBAGB5CxkBAAwHAYDVR0RBBUwE4IRZGV2MC52aWRpdmlldy5jb20wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGCisGAQQBgeQsg3QEBDEzMjgwEwYKKwYBBAGB5CyDdwQFNjk2NDgwEAYKKwYBBAGB5CyDdQQCNDgwEgYKKwYBBAGB5CyDdgQENDExMjAPBgkrBgEEAYHkLGkEAjE2MA0GCSqGSIb3DQEBCwUAA4ICAQCpKPR6J5fMf4cWQpnEzYe7pT1xgg2QQA7FjauujHTPyFGV6Wrx6TLgm2os998ISSSxcCygbR0XtOpiyCvHw1GTgJHEMWmbmBqE4m3k0bLT3xQLMOeuwN45PKOB8meiPAzjoJSU9WBsZiY5bzAHyBxz+0TzR9+xQMVxdY6Lkfo6owXAzevroxNw9+WZXRuhNyAJxepALeoOB9ugNK50c/CK9qZYdZhLBt3qf+d7g91/q+FDbWFGO0uxOdfi2ddiDhP1olpjFsu4XbgrLv6+Aqczg5ulO6QVpiqu0/K1nP/aY8nrOoRrQMr6DmSa48/cSDZmDCQSTnA1hEh3N51/FlN6fRCKTErym2QaTmj/W1/WxZYrrk8SzK53kI3zkj057Tx7m4D+5suFxWR3VNhhE93hTQEc1qrSkuvKXIvqel0KkxRY2Boadm18Dud04gqLd8z6NELi9wSj7q9Rho/F671H57ETQCPWKzmJn7Y+XgG/ARp1TtHQXtcyBjH7mwu8LlNtO41Sgnd95od83hNWpDeVTJ5fJO63UckeuD64C+T6aIaZhDoiFY2oSw75yGZ5Bg9TokNLlOLUABk5FBYlbjBDk00+5HTpVmQO4e8n5ssdNI0KLgLfSriKyXGu+POeFqEv561n/1SxLwyvUiSvMVXPfxgRQnlN0AH9q5MAG4XgkA=="); var issuerBlob = System.Convert.FromBase64String("MIIFTzCCAzegAwIBAgIQGiooCWlWUr9EvAa05KWP2jANBgkqhkiG9w0BAQsFADBTMSMwIQYDVQQDExpWaWRpVmlldyBMaWNlbnNlIEF1dGhvcml0eTEfMB0GA1UEChMWRGlzdHJpYnV0ZWQgTWVkaWNhbCBBQjELMAkGA1UEBhMCU0UwIBcNMTYxMDI1MDcyMDEyWhgPMjA3OTEyMzEwMDAwMDBaMFMxIzAhBgNVBAMTGlZpZGlWaWV3IExpY2Vuc2UgQXV0aG9yaXR5MR8wHQYDVQQKExZEaXN0cmlidXRlZCBNZWRpY2FsIEFCMQswCQYDVQQGEwJTRTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvUTa+JNG5L60mCZAAztFoYCUBMGs76Yk/7+a0DCfuNY367uUx8L1Qne6S2ei0awQiEBgrndeCSXV7Y8avCdaLZjAv85YLwuYf3J94K2Xj6HDqWsTxJ4H0o6tuL2pmY+cz99AIZA3nPWMF0FfneeM+pxo7sZ4IBhzqaNKSluhjE9ReS1h+230n6/lzvCPv3iw2ksnvKTNXKELUGA6kXJzSRPU/vhRDqtdAjJp+YkhpHr5VP3Gz4glUx3mobVOb7u/xJDll6f2IIn8O/BrgkatBbEmKcoJOMcmFJclcjBz8ZCfHmK9KQuk73nU+Ijuo5UugBx+cuZ6R3GrV2c4fmIcRChCNsO6Hs34uqM94ATzwydzZ4I6Vpk4f6PR8N8rk4ZoDmaQXd/s1cARxVH49ts6C201ygQ8wD2ds7GOD9RtoQ2VsNl4Nrzo0p8THPx7tMJyLy2GjdJiMtlQ6AFezeH0BkERmswU+CXyNHR6jfuWcnse0c+KhK4OUkUfb7t61Igfiu8LwPyvOtd9/lJZgt0kXcMBvYwaSR2VwSiHXtVf7lcrJr+w17ytZgVCuot2+5SJ8Aa1QEFR+KtzYYmtbGU/PvZgNjGwYMpYrPrZikf6xPSQDb9954bB6sj8BOy6tb7+DjkkYK8FkjEd2uaM5F+JD0Zv1cqMVlLx+PtYrZxy1LAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MA0GCSqGSIb3DQEBCwUAA4ICAQCEMicj4FxdXn5nItAUoJ2oAtOPIMpp3sUnBWtNq0EYViCD7JfjJc1q2BFhgXwSQMqzPZ3onZlryms68ygdLMDav2aUjrzfrM82ncX1aZBso6Vdl0GS/HDA38aX5wTTEjpv3LueFbOm3x4vh6WDPaWDBssgtEefx6tdzTWK3XOYaHhDw5fnn1k1NNUa3Yx1DJ2HuXxnULJkgdjIDGIZuZ5wduB3OKqiV673OKnKMppPXDLNamVg63gco420sfcqgm3xU0PYDKkPIJ6P1HU3A/MdIlLEE+VaHDqvbPcckSQZALsiDrIHqK1vSgbCYdaeEXqCE6EVT1kLiYS6u+TDQfNQy+VNpTwyleqpbBvIrEJ5/qYRBs2fq7BPceZG+Pa2PH8svqMypTkB0gLwMY2jMLl0ckZkyHD0fcJsKxlAEUNwzcai8z1d2wBHBfDuYsh54+F4PB5bqT031nbTHewjQYhW0GvexI1r9qT9O/d+vP21g62DIJ3TVTH5cYPySx4H2vuAW3a+umX1E1jV18FKPMDxESuS8WfOCofGkgNVgCfEvXbu730pAT50TY6YDt+a713LDFTQpMyhL+2NRUS+emE8nxrrCWlhEhZhqYW7RBTg1yR+Ohja4RESilZ9D4BJNSMxZC2u37Uf8A6kbLnykGulQhW18iZk8BtT4sfG+iII4A==");

    var childCert = new Windows.Security.Cryptography.Certificates.Certificate(childBlob.AsBuffer());
    var issuerCert = new Windows.Security.Cryptography.Certificates.Certificate(issuerBlob.AsBuffer());

    var builderParams = new Windows.Security.Cryptography.Certificates.ChainBuildingParameters()
    {
        CurrentTimeValidationEnabled = true,
        NetworkRetrievalEnabled = false,
        RevocationCheckEnabled = false,
    };
    
    builderParams.ExclusiveTrustRoots.Add(issuerCert);

    var result = await childCert.BuildChainAsync(new[] { issuerCert }, builderParams);

    var r = result.Validate();
    System.Diagnostics.Debug.Assert(r == Windows.Security.Cryptography.Certificates.ChainValidationResult.Success);
}

`

Expected behavior

I would expect the code to successfully validate the certificate if it is issued by one of the certificates in the ExclusiveTrustRoot with a result of ChainValidationResult.Success.

Also, if the certificate is issued by any other authority (even the ones installed in the Trusted Root Store), it should succeed but return ChainValidationResult.Untrusted since the trust list is exclusive.

Screenshots

No response

NuGet package version

Windows App SDK 1.3.0: 1.3.230331000

Packaging type

No response

Windows version

Windows 11 version 22H2 (22621, 2022 Update)

IDE

Visual Studio 2022

Additional context

No response

bjorn-malmo avatar May 02 '23 11:05 bjorn-malmo

@bjorn-malmo Can you help us understand how this is connected with Windows App SDK? Did the blobs in question come from the signature on a Windows App SDK binary?

Scottj1s avatar May 04 '23 17:05 Scottj1s

The same two certificates as in the previous example, will work as expected with the X509Chain class to validate a child certificate with a specific trusted root (not present in the Trusted Certificate Root store), as in the following example.

The problem I'm trying to solve is connecting to a host having a certificate that is issued by an internal authority, and this should be verified by the client. The client will never have this issuer in the Trusted Root store though. Using X509Certificate2 and X509Chain, the custom issuer can be added to the chain and hereafter successfully validate.

However, using the newer Windows...Certificate does not work as in the previous sample.

    public static async Task VerifyLegacyCertificate()
    {
        var childBlob = System.Convert.FromBase64String("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");
        var issuerBlob = System.Convert.FromBase64String("MIIFTzCCAzegAwIBAgIQGiooCWlWUr9EvAa05KWP2jANBgkqhkiG9w0BAQsFADBTMSMwIQYDVQQDExpWaWRpVmlldyBMaWNlbnNlIEF1dGhvcml0eTEfMB0GA1UEChMWRGlzdHJpYnV0ZWQgTWVkaWNhbCBBQjELMAkGA1UEBhMCU0UwIBcNMTYxMDI1MDcyMDEyWhgPMjA3OTEyMzEwMDAwMDBaMFMxIzAhBgNVBAMTGlZpZGlWaWV3IExpY2Vuc2UgQXV0aG9yaXR5MR8wHQYDVQQKExZEaXN0cmlidXRlZCBNZWRpY2FsIEFCMQswCQYDVQQGEwJTRTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvUTa+JNG5L60mCZAAztFoYCUBMGs76Yk/7+a0DCfuNY367uUx8L1Qne6S2ei0awQiEBgrndeCSXV7Y8avCdaLZjAv85YLwuYf3J94K2Xj6HDqWsTxJ4H0o6tuL2pmY+cz99AIZA3nPWMF0FfneeM+pxo7sZ4IBhzqaNKSluhjE9ReS1h+230n6/lzvCPv3iw2ksnvKTNXKELUGA6kXJzSRPU/vhRDqtdAjJp+YkhpHr5VP3Gz4glUx3mobVOb7u/xJDll6f2IIn8O/BrgkatBbEmKcoJOMcmFJclcjBz8ZCfHmK9KQuk73nU+Ijuo5UugBx+cuZ6R3GrV2c4fmIcRChCNsO6Hs34uqM94ATzwydzZ4I6Vpk4f6PR8N8rk4ZoDmaQXd/s1cARxVH49ts6C201ygQ8wD2ds7GOD9RtoQ2VsNl4Nrzo0p8THPx7tMJyLy2GjdJiMtlQ6AFezeH0BkERmswU+CXyNHR6jfuWcnse0c+KhK4OUkUfb7t61Igfiu8LwPyvOtd9/lJZgt0kXcMBvYwaSR2VwSiHXtVf7lcrJr+w17ytZgVCuot2+5SJ8Aa1QEFR+KtzYYmtbGU/PvZgNjGwYMpYrPrZikf6xPSQDb9954bB6sj8BOy6tb7+DjkkYK8FkjEd2uaM5F+JD0Zv1cqMVlLx+PtYrZxy1LAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MA0GCSqGSIb3DQEBCwUAA4ICAQCEMicj4FxdXn5nItAUoJ2oAtOPIMpp3sUnBWtNq0EYViCD7JfjJc1q2BFhgXwSQMqzPZ3onZlryms68ygdLMDav2aUjrzfrM82ncX1aZBso6Vdl0GS/HDA38aX5wTTEjpv3LueFbOm3x4vh6WDPaWDBssgtEefx6tdzTWK3XOYaHhDw5fnn1k1NNUa3Yx1DJ2HuXxnULJkgdjIDGIZuZ5wduB3OKqiV673OKnKMppPXDLNamVg63gco420sfcqgm3xU0PYDKkPIJ6P1HU3A/MdIlLEE+VaHDqvbPcckSQZALsiDrIHqK1vSgbCYdaeEXqCE6EVT1kLiYS6u+TDQfNQy+VNpTwyleqpbBvIrEJ5/qYRBs2fq7BPceZG+Pa2PH8svqMypTkB0gLwMY2jMLl0ckZkyHD0fcJsKxlAEUNwzcai8z1d2wBHBfDuYsh54+F4PB5bqT031nbTHewjQYhW0GvexI1r9qT9O/d+vP21g62DIJ3TVTH5cYPySx4H2vuAW3a+umX1E1jV18FKPMDxESuS8WfOCofGkgNVgCfEvXbu730pAT50TY6YDt+a713LDFTQpMyhL+2NRUS+emE8nxrrCWlhEhZhqYW7RBTg1yR+Ohja4RESilZ9D4BJNSMxZC2u37Uf8A6kbLnykGulQhW18iZk8BtT4sfG+iII4A==");

        var childCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(childBlob);
        var issuerCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(issuerBlob);

        using var chain = new System.Security.Cryptography.X509Certificates.X509Chain();
        chain.ChainPolicy.RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck;
        bool success = chain.Build(childCert);
        System.Diagnostics.Debug.Assert(success == false);

        using var chainWithCustomIssuer = new System.Security.Cryptography.X509Certificates.X509Chain();
        chainWithCustomIssuer.ChainPolicy.RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck;
        chainWithCustomIssuer.ChainPolicy.TrustMode = System.Security.Cryptography.X509Certificates.X509ChainTrustMode.CustomRootTrust;
        chainWithCustomIssuer.ChainPolicy.CustomTrustStore.Add(issuerCert);
        success = chain.Build(childCert);
        System.Diagnostics.Debug.Assert(success == true);

    }

bjorn-malmo avatar May 05 '23 15:05 bjorn-malmo

I have the exact same issue.

luihabl avatar Jan 17 '24 17:01 luihabl