namespace {
const char* CERT[] = {
+ // EQUIFAX ROOT CA
"-----BEGIN CERTIFICATE-----\n"
- "MIIF0TCCBLmgAwIBAgIQaPGTP4aS7Ut/WDNaBzdQrDANBgkqhkiG9w0BAQUFADCB\n"
- "ujELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n"
- "ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug\n"
- "YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE0MDIGA1UEAxMr\n"
- "VmVyaVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBDQTAeFw0x\n"
- "NDAyMjAwMDAwMDBaFw0xNTAyMjAyMzU5NTlaMIHmMRMwEQYLKwYBBAGCNzwCAQMT\n"
- "AlBMMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjETMBEGA1UEBRMKMDAw\n"
- "MDAyNTIzNzELMAkGA1UEBhMCUEwxDzANBgNVBBEUBjAwLTk1MDEUMBIGA1UECBML\n"
- "bWF6b3dpZWNraWUxETAPBgNVBAcUCFdhcnN6YXdhMRYwFAYDVQQJFA1TZW5hdG9y\n"
- "c2thIDE4MRMwEQYDVQQKFAptQmFuayBTLkEuMQwwCgYDVQQLFANESU4xGTAXBgNV\n"
- "BAMUEHd3dy5tYmFuay5jb20ucGwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n"
- "AoIBAQDph6x8V6xUW/+651+qHF+UmorH9uaz2ZrX2bIWiMKIJFmpDDHlxcapKkqE\n"
- "BV04is83aiCpqKtc2ZHy2g4Hpj1eSF5BP2+OAlo0YUQZPIeRRdiMjmeAxw/ncBDx\n"
- "9rQBuCJ4XTD6cqQox5SI0TASOZ+wyAEjbDRXzL73XqRAFZ1LOpb2ONkolS+RutMB\n"
- "vshvCsWPeNe7eGLuOh6DyC6r1vX9xhw3xnjM2mTSvmtimgzSLacNGKqRrsucUgcb\n"
- "0+O5C2jZAtAMLyZksL92cxmWbtVzUYzem4chjHu5cRxUlPNzUJWrrczueB7Ip4A8\n"
- "aQuFMfNXYc0x+WLWjy//urypMKjhAgMBAAGjggGjMIIBnzAbBgNVHREEFDASghB3\n"
- "d3cubWJhbmsuY29tLnBsMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgWgMB0GA1Ud\n"
- "JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBEBgNVHSAEPTA7MDkGC2CGSAGG+EUB\n"
- "BxcGMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9jcHMw\n"
- "HQYDVR0OBBYEFN37iGaS7mZnENxZ9FGqNLR+QgoMMB8GA1UdIwQYMBaAFPyKULqe\n"
- "uSVae1WFT5UAY4/pWGtDMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9FVlNlY3Vy\n"
- "ZS1jcmwudmVyaXNpZ24uY29tL0VWU2VjdXJlMjAwNi5jcmwwfAYIKwYBBQUHAQEE\n"
- "cDBuMC0GCCsGAQUFBzABhiFodHRwOi8vRVZTZWN1cmUtb2NzcC52ZXJpc2lnbi5j\n"
- "b20wPQYIKwYBBQUHMAKGMWh0dHA6Ly9FVlNlY3VyZS1haWEudmVyaXNpZ24uY29t\n"
- "L0VWU2VjdXJlMjAwNi5jZXIwDQYJKoZIhvcNAQEFBQADggEBAD0wO+rooUrIM4qp\n"
- "PHhp+hkXK6WMQ2qzGOmbMcZjw0govg5vkzkefPDryIXXbrF8mRagiJNMSfNaWWeh\n"
- "Cj41OV24EdUl0OLbFxNzcvub599zRs/apfaRLTfsmlmOgi0/YP305i+3tJ2ll946\n"
- "P+qV1wXnXqTqEdIl4Ys3+1HmDCdTB1hoDwAAzqRVUXZ5+iiwPAU7R/LTHfMjV1ke\n"
- "8jtNFfrorlZMCfVH/7eEnHJvVjOJt+YFe4aFMzE+DfuYIK7MH+olC2v79kBwbnEQ\n"
- "fvHMA9gFwOYLUBBdSfcocp8EKZ+mRlNPGR/3LBrPeaQQ0GZEkxzRK+v/aNTuiYfr\n"
- "oFXtrg0=\n"
+ "MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV\n"
+ "UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy\n"
+ "dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1\n"
+ "MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx\n"
+ "dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B\n"
+ "AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f\n"
+ "BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A\n"
+ "cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC\n"
+ "AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ\n"
+ "MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm\n"
+ "aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw\n"
+ "ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj\n"
+ "IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF\n"
+ "MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA\n"
+ "A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y\n"
+ "7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh\n"
+ "1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n"
"-----END CERTIFICATE-----\n",
+ // GeoTrust Global CA - issued by Equifax
"-----BEGIN CERTIFICATE-----\n"
- "MIIF5DCCBMygAwIBAgIQW3dZxheE4V7HJ8AylSkoazANBgkqhkiG9w0BAQUFADCB\n"
- "yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n"
- "ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\n"
- "U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\n"
- "ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\n"
- "aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMTYxMTA3MjM1OTU5WjCBujEL\n"
- "MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW\n"
- "ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQg\n"
- "aHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE0MDIGA1UEAxMrVmVy\n"
- "aVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBDQTCCASIwDQYJ\n"
- "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAJjboFXrnP0XeeOabhQdsVuYI4cWbod2\n"
- "nLU4O7WgerQHYwkZ5iqISKnnnbYwWgiXDOyq5BZpcmIjmvt6VCiYxQwtt9citsj5\n"
- "OBfH3doxRpqUFI6e7nigtyLUSVSXTeV0W5K87Gws3+fBthsaVWtmCAN/Ra+aM/EQ\n"
- "wGyZSpIkMQht3QI+YXZ4eLbtfjeubPOJ4bfh3BXMt1afgKCxBX9ONxX/ty8ejwY4\n"
- "P1C3aSijtWZfNhpSSENmUt+ikk/TGGC+4+peGXEFv54cbGhyJW+ze3PJbb0S/5tB\n"
- "Ml706H7FC6NMZNFOvCYIZfsZl1h44TO/7Wg+sSdFb8Di7Jdp91zT91ECAwEAAaOC\n"
- "AdIwggHOMB0GA1UdDgQWBBT8ilC6nrklWntVhU+VAGOP6VhrQzASBgNVHRMBAf8E\n"
- "CDAGAQH/AgEAMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRw\n"
- "czovL3d3dy52ZXJpc2lnbi5jb20vY3BzMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6\n"
- "Ly9FVlNlY3VyZS1jcmwudmVyaXNpZ24uY29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB\n"
- "/wQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZ\n"
- "MFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7\n"
- "GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwKQYDVR0R\n"
- "BCIwIKQeMBwxGjAYBgNVBAMTEUNsYXNzM0NBMjA0OC0xLTQ3MD0GCCsGAQUFBwEB\n"
- "BDEwLzAtBggrBgEFBQcwAYYhaHR0cDovL0VWU2VjdXJlLW9jc3AudmVyaXNpZ24u\n"
- "Y29tMB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqGSIb3DQEB\n"
- "BQUAA4IBAQCWovp/5j3t1CvOtxU/wHIDX4u6FpAl98KD2Md1NGNoElMMU4l7yVYJ\n"
- "p8M2RE4O0GJis4b66KGbNGeNUyIXPv2s7mcuQ+JdfzOE8qJwwG6Cl8A0/SXGI3/t\n"
- "5rDFV0OEst4t8dD2SB8UcVeyrDHhlyQjyRNddOVG7wl8nuGZMQoIeRuPcZ8XZsg4\n"
- "z+6Ml7YGuXNG5NOUweVgtSV1LdlpMezNlsOjdv3odESsErlNv1HoudRETifLriDR\n"
- "fip8tmNHnna6l9AW5wtsbfdDbzMLKTB3+p359U64drPNGLT5IO892+bKrZvQTtKH\n"
- "qQ2mRHNQ3XBb7a1+Srwi1agm5MKFIA3Z\n"
+ "MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT\n"
+ "MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0\n"
+ "aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw\n"
+ "WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE\n"
+ "AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"
+ "CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m\n"
+ "OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu\n"
+ "T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c\n"
+ "JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR\n"
+ "Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz\n"
+ "PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm\n"
+ "aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM\n"
+ "TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g\n"
+ "LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO\n"
+ "BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv\n"
+ "dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB\n"
+ "AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL\n"
+ "NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W\n"
+ "b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S\n"
+ "-----END CERTIFICATE-----\n",
+
+ // Google Internet Authority G2 - issued by GeoTrust Global CA
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n"
+ "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\n"
+ "YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG\n"
+ "EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy\n"
+ "bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+ "AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP\n"
+ "VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv\n"
+ "h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE\n"
+ "ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ\n"
+ "EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC\n"
+ "DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7\n"
+ "qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD\n"
+ "VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g\n"
+ "K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI\n"
+ "KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n\n"
+ "ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB\n"
+ "BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY\n"
+ "/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/\n"
+ "zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza\n"
+ "HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto\n"
+ "WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6\n"
+ "yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx\n"
+ "-----END CERTIFICATE-----\n",
+
+ // *.google.com - issued by Google Internet Authority
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIGxTCCBa2gAwIBAgIIAl5EtcNJFrcwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE\n"
+ "BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl\n"
+ "cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQxMjEwMTEzMzM3WhcNMTUwMzEwMDAwMDAw\n"
+ "WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN\n"
+ "TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n\n"
+ "b29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmng6ZoVeVmmAplSC\n"
+ "9TcTQkkosO5zaPDTXLuuzQU3Bl5JUSF/11w6dlXdJJHXIQ3cIirUuyd288ORbu93\n"
+ "FrTTTaOCBF0wggRZMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjCCAyYG\n"
+ "A1UdEQSCAx0wggMZggwqLmdvb2dsZS5jb22CDSouYW5kcm9pZC5jb22CFiouYXBw\n"
+ "ZW5naW5lLmdvb2dsZS5jb22CEiouY2xvdWQuZ29vZ2xlLmNvbYIWKi5nb29nbGUt\n"
+ "YW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xlLmNsgg4qLmdvb2ds\n"
+ "ZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNvLnVrgg8qLmdvb2ds\n"
+ "ZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUuY29tLmJygg8qLmdv\n"
+ "b2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29nbGUuY29tLnRygg8q\n"
+ "Lmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2dsZS5lc4ILKi5nb29n\n"
+ "bGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5nb29nbGUubmyCCyou\n"
+ "Z29vZ2xlLnBsggsqLmdvb2dsZS5wdIISKi5nb29nbGVhZGFwaXMuY29tgg8qLmdv\n"
+ "b2dsZWFwaXMuY26CFCouZ29vZ2xlY29tbWVyY2UuY29tghEqLmdvb2dsZXZpZGVv\n"
+ "LmNvbYIMKi5nc3RhdGljLmNugg0qLmdzdGF0aWMuY29tggoqLmd2dDEuY29tggoq\n"
+ "Lmd2dDIuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIMKi51cmNoaW4uY29tghAq\n"
+ "LnVybC5nb29nbGUuY29tghYqLnlvdXR1YmUtbm9jb29raWUuY29tgg0qLnlvdXR1\n"
+ "YmUuY29tghYqLnlvdXR1YmVlZHVjYXRpb24uY29tggsqLnl0aW1nLmNvbYILYW5k\n"
+ "cm9pZC5jb22CBGcuY2+CBmdvby5nbIIUZ29vZ2xlLWFuYWx5dGljcy5jb22CCmdv\n"
+ "b2dsZS5jb22CEmdvb2dsZWNvbW1lcmNlLmNvbYIKdXJjaGluLmNvbYIIeW91dHUu\n"
+ "YmWCC3lvdXR1YmUuY29tghR5b3V0dWJlZWR1Y2F0aW9uLmNvbTALBgNVHQ8EBAMC\n"
+ "B4AwaAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2ds\n"
+ "ZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29v\n"
+ "Z2xlLmNvbS9vY3NwMB0GA1UdDgQWBBTn6rT+UWACLuZnUas2zTQJkdrq5jAMBgNV\n"
+ "HRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1Ud\n"
+ "IAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtp\n"
+ "Lmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBb4wU7IjXL\n"
+ "msvaYqFlYYDKiYZhBUGHxxLkFWR72vFugYkJ7BbMCaKZJdyln5xL4pCdNHiNGfub\n"
+ "/3ct2t3sKeruc03EydznLQ78qrHuwNJdqUZfDLJ6ILAQUmpnYEXrnmB7C5chCWR0\n"
+ "OKWRLguwZQQQQlRyjZFtdoISHNveel/UkS/Jwijvpbw/wGg9W4L4En6RjDeD259X\n"
+ "zYvNzIwiEq50/5ZQCYE9EH0mWguAji9tuh5NJKPEeaaCQ3lp/UEAkq5uYls7tuSs\n"
+ "MTI9LMZRiYFJab/LYbq2uaz4B/lSuE9vku+ikNYA+J2Qv6eqU3U+jmUOSCfYJ2Qt\n"
+ "zSl8TUu4bL8a\n"
+ "-----END CERTIFICATE-----\n",
+
+ // Test root ca
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDnzCCAoegAwIBAgIJAMH/ADkC5YSTMA0GCSqGSIb3DQEBBQUAMGYxCzAJBgNV\n"
+ "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDARBQ01FMRAwDgYD\n"
+ "VQQLDAdUZXN0aW5nMSEwHwYDVQQDDBhUZXN0IHJvb3QgY2EgY2VydGlmaWNhdGUw\n"
+ "HhcNMTQxMjMwMTcyMTUyWhcNMjQxMjI3MTcyMTUyWjBmMQswCQYDVQQGEwJBVTET\n"
+ "MBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UECgwEQUNNRTEQMA4GA1UECwwHVGVz\n"
+ "dGluZzEhMB8GA1UEAwwYVGVzdCByb290IGNhIGNlcnRpZmljYXRlMIIBIjANBgkq\n"
+ "hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0EJRdUtd2th0vTVF7QxvDKzyFCF3w9vC\n"
+ "9IDE/Yr12w+a9jd0s7/eG96qTHIYffS3B7x2MB+d4n+SR3W0qmYh7xk8qfEgH3da\n"
+ "eDoV59IZ9r543KM+g8jm6KffYGX1bIJVVY5OhBRbO9nY6byYpd5kbCIUB6dCf7/W\n"
+ "rQl1aIdLGFIegAzPGFPXDcU6F192686x54bxt/itMX4agHJ9ZC/rrTBIZghVsjJo\n"
+ "5/AH5WZpasv8sfrGiiohAxtieoYoJkv5MOYP4/2lPlOY+Cgw1Yoz+HHv31AllgFs\n"
+ "BquBb/kJVmCCNsAOcnvQzTZUsW/TXz9G2nwRdqI1nSy2JvVjZGsqGQIDAQABo1Aw\n"
+ "TjAdBgNVHQ4EFgQUt6pkzFt1PZlfYRL/HGnufF4frdwwHwYDVR0jBBgwFoAUt6pk\n"
+ "zFt1PZlfYRL/HGnufF4frdwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC\n"
+ "AQEAld7Qwq0cdzDQ51w1RVLwTR8Oy25PB3rzwEHcSGJmdqlMi3xOdaz80S1R1BBX\n"
+ "ldvGBG5Tn0vT7xSuhmSgI2/HnBpy9ocHVOmhtNB4473NieEpfTYrnGXrFxu46Wus\n"
+ "9m/ZnugcQ2G6C54A/NFtvgLmaC8uH8M7gKdS6uYUwJFQEofkjmd4UpOYSqmcRXhS\n"
+ "Jzd5FYFWkJhKJYp3nlENSOD8CUFFVGekm05nFN2gRVc/qaqQkEX77+XYvhodLRsV\n"
+ "qMn7nf7taidDKLO2T4bhujztnTYOhhaXKgPy7AtZ28N2wvX96VyAPB/vrchGmyBK\n"
+ "kOg11TpPdNDkhb1J4ZCh2gupDg==\n"
+ "-----END CERTIFICATE-----\n",
+
+ // Test intermediate ca signed with test root ca
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDljCCAn6gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwZjELMAkGA1UEBhMCQVUx\n"
+ "EzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoMBEFDTUUxEDAOBgNVBAsMB1Rl\n"
+ "c3RpbmcxITAfBgNVBAMMGFRlc3Qgcm9vdCBjYSBjZXJ0aWZpY2F0ZTAeFw0xNTAx\n"
+ "MTYxNjQ1MzRaFw0zNTAxMTExNjQ1MzRaMGQxCzAJBgNVBAYTAkFVMRMwEQYDVQQI\n"
+ "DApTb21lLVN0YXRlMQ0wCwYDVQQKDARBQ01FMRAwDgYDVQQLDAdUZXN0aW5nMR8w\n"
+ "HQYDVQQDDBZUZXN0IElNIENBIGNlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEF\n"
+ "AAOCAQ8AMIIBCgKCAQEAzmBF78qClgoKfnLAncMXZwZ14TW+5kags1+QCYeg3c7j\n"
+ "L9+RvDxIaX2tKf1sukJcwQfYqUlQkwt+58LMOb2ORtkpj8Or6WCWCZ0BzneT8ug7\n"
+ "nxJT4m9+bohMF0JoKjjB2H4KNMHamLIwUxRKt6nyfk81kVhJOi2vzzxd+UCPi6Pc\n"
+ "UAbJNH48eNgOIg55nyFovVzYj8GIo/9GvHJj83PPa/KlJZ+Z1qZASZZ/VYorplVT\n"
+ "thsHXKfejhFy5YJ9t7n/vyAQsyBsagZsvX19xnH41fbYXHKf8UbXG23rNaZlchs6\n"
+ "XJVLQdzOpj3WTj/lCocVHqLaZISLhNQ3aI7kUBUdiwIDAQABo1AwTjAdBgNVHQ4E\n"
+ "FgQUoCYNaCBP4jl/3SYQuK8Ka+6i3QEwHwYDVR0jBBgwFoAUt6pkzFt1PZlfYRL/\n"
+ "HGnufF4frdwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAjRzWiD97\n"
+ "Htv4Kxpm3P+C+xP9AEteCJfO+7p8MWgtWEJOknJyt55zeKS2JwZIq57KcbqD8U7v\n"
+ "vAUx1ymtUhlFPFd7J1mJ3pou+3aFYmGShYhGHpbrmUwjp7HVP588jrW1NoZVHdMc\n"
+ "4OgJWFrViXeu9+maIcekjMB/+9Y0dUgQuK5ZuT5H/Jwet7Th/o9uufTUZjBzRvrB\n"
+ "pbXgQpqgME2av4Q/6LuldPCTHLtWXgFUU2R+yCGmuGilvhFJnKoQryAbYnIQNWE8\n"
+ "SLoHQ9s1i7Zyb7HU6UAaqMOz15LBkyAqtNyJcO2p7Q/p5YK0xfD4xisI5qXucqVm\n"
+ "F2obL5qJSTN/RQ==\n"
+ "-----END CERTIFICATE-----\n",
+
+ // Test certificate signed with test intermediate ca
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDOzCCAiMCAQEwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCQVUxEzARBgNV\n"
+ "BAgMClNvbWUtU3RhdGUxDTALBgNVBAoMBEFDTUUxEDAOBgNVBAsMB1Rlc3Rpbmcx\n"
+ "HzAdBgNVBAMMFlRlc3QgSU0gQ0EgY2VydGlmaWNhdGUwHhcNMTUwMTE2MTY0ODE0\n"
+ "WhcNMzUwMTExMTY0ODE0WjBjMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1T\n"
+ "dGF0ZTENMAsGA1UECgwEQUNNRTEQMA4GA1UECwwHVGVzdGluZzEeMBwGA1UEAwwV\n"
+ "VGVzdCBsZWFmIGNlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"
+ "CgKCAQEAzTdDIa2tDmRxFnIgiG+mBz8GoSVODs0ImNQGbqj+pLhBOFRH8fsah4Jl\n"
+ "z5YF9KwhMVLknnHGFLE/Nb7Ac35kEzhMQMpTRxohW83oxw3eZ8zN/FBoKqg4qHRq\n"
+ "QR8kS10YXTgrBR0ex/Vp+OUKEw6h7yL2r4Tpvrn9/qHwsxtLxqWbDIVf1O9b1Lfc\n"
+ "bllYMdmV5E62yN5tcwrDP8gvHjFnVeLzrG8wTpc9FR90/0Jkfp5jAJcArOBLrT0E\n"
+ "4VRqs+4HuwT8jAwFAmNnc7IYX5qSjtSWkmmHe73K/lzB+OiI0JEc/3eWUTWqwTSk\n"
+ "4tNCiQGBKJ39LXPTBBJdzmxVH7CUDQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAp\n"
+ "UdDOGu3hNiG+Vn10aQ6B1ZmOj3t+45gUV3sC+y8hB8EK1g4P5Ke9bVDts0T5eOnj\n"
+ "CSc+6VoND5O4adI0IFFRFljHNVnvjeosHfUZNnowsmA2ptQBtC1g5ZKRvKXlkC5/\n"
+ "i5BGgRqPFA7y9WB9Y05MrJHf3E+Oz/RBsLeeNiNN+rF5X1vYExvGHpo0M0zS0ze9\n"
+ "HtC0aOy8ocsTrQkf3ceHTAXx2i8ftoSSD4klojtWFpWMrNQa52F7wB9nU6FfKRuF\n"
+ "Zj/T1JkYXKkEwZU6nAR2jdZp3EP9xj3o15V/tyFcXHx6l8NTxn4cJb+Xe4VquQJz\n"
+ "6ON7PVe0ABN/AlwVQiFE\n"
"-----END CERTIFICATE-----\n",
};
// index of CERT array
enum CertIdx{
- CERT_EE,
- CERT_IM,
+ CERT_ROOT_CA, // system root ca cert
+ CERT_IM_CA1, // ca cert signed with CERT_ROOT_CA (also present as system root ca (sic!))
+ CERT_IM_CA2, // ca cert signed with CERT_IM_CA1
+ CERT_LEAF, // cert signed with CERT_IM_CA2
+ CERT_TEST_ROOT_CA, // test root ca cert
+ CERT_TEST_IM_CA, // test im ca cert signed with CERT_TEST_ROOT_CA
+ CERT_TEST_LEAF, // test certificate signed with CERT_TEST_IM_CA
};
template <typename F, typename... Args>
assert_result(CKMC_ERROR_NONE, std::move(func), args...);
}
+template <typename F, typename... Args>
+void assert_invalid_param(F&& func, Args... args)
+{
+ assert_result(CKMC_ERROR_INVALID_PARAMETER, std::move(func), args...);
+}
+
template <typename T>
size_t list_size(const T* list)
{
return size;
}
-template <typename T>
-void assert_list_size(const T* list, size_t expected)
-{
- size_t size = list_size(list);
- RUNNER_ASSERT_MSG_BT(size == expected, "Expected chain size: " << expected << " got: " << size);
-}
-
typedef std::unique_ptr<ckmc_cert_s, void (*)(ckmc_cert_s*)> CertPtr;
typedef std::unique_ptr<ckmc_cert_list_s, void (*)(ckmc_cert_list_s*)> CertListPtr;
typedef std::unique_ptr<ckmc_alias_list_s, void (*)(ckmc_alias_list_s*)> AliasListPtr;
-CertPtr create_cert(CertIdx idx) {
+ckmc_cert_s* create_cert(CertIdx idx) {
size_t size = sizeof(CERT)/sizeof(CERT[0]);
RUNNER_ASSERT_MSG_BT(idx < size, "Certificate index out of range: " << idx << ">=" << size);
&cert);
RUNNER_ASSERT_MSG_BT(cert != NULL, "Cert is NULL");
- CertPtr c(cert, ckmc_cert_free);
- return c;
+ return cert;
}
-void save_cert(const CertPtr& cert, const char* alias) {
+void save_cert(const ckmc_cert_s* cert, const char* alias) {
ckmc_policy_s policy;
policy.password = NULL;
policy.extractable = 1;
return certList;
}
-const ckmc_cert_list_s* NULL_CERTS = NULL;
const ckmc_alias_list_s* NULL_ALIASES = NULL;
+const ckmc_cert_s* NULL_CERT = NULL;
+ckmc_cert_list_s** NULL_CHAIN = NULL;
+
+// old api wrapper
+class ChainApiOld {
+public:
+ static int createChain(const ckmc_cert_s *cert,
+ const ckmc_cert_list_s *untrustedcerts,
+ const ckmc_cert_list_s* /*trustedcerts*/,
+ const bool /*use_trustedsystemcerts*/,
+ ckmc_cert_list_s **ppcert_chain_list)
+ {
+ return ckmc_get_cert_chain(cert, untrustedcerts, ppcert_chain_list);
+ }
+
+ static int createChainWithAlias(const ckmc_cert_s *cert,
+ const ckmc_alias_list_s *untrustedcerts,
+ const ckmc_alias_list_s* /*trustedcerts*/,
+ const bool /*use_trustedsystemcerts*/,
+ ckmc_cert_list_s **ppcert_chain_list)
+ {
+ return ckmc_get_cert_chain_with_alias(cert, untrustedcerts, ppcert_chain_list);
+ }
+};
+
+// new api wrapper
+class ChainApiNew {
+public:
+ static int createChain(const ckmc_cert_s *cert,
+ const ckmc_cert_list_s *untrustedcerts,
+ const ckmc_cert_list_s *trustedcerts,
+ const bool use_trustedsystemcerts,
+ ckmc_cert_list_s **ppcert_chain_list)
+ {
+ return ckmc_get_certificate_chain(cert,
+ untrustedcerts,
+ trustedcerts,
+ use_trustedsystemcerts,
+ ppcert_chain_list);
+ }
+
+ static int createChainWithAlias(const ckmc_cert_s *cert,
+ const ckmc_alias_list_s *untrustedcerts,
+ const ckmc_alias_list_s *trustedcerts,
+ const bool use_trustedsystemcerts,
+ ckmc_cert_list_s **ppcert_chain_list)
+ {
+ return ckmc_get_certificate_chain_with_alias(cert,
+ untrustedcerts,
+ trustedcerts,
+ use_trustedsystemcerts,
+ ppcert_chain_list);
+ }
+};
+
+/*
+ * Helper class for certificate verification
+ */
+template <typename T=ChainApiNew>
+class ChainVerifier
+{
+public:
+ ChainVerifier();
+ ~ChainVerifier();
+
+ void addTrusted(CertIdx idx);
+ void addUntrusted(CertIdx idx);
+ void enableSystem(bool enable);
+
+ void verifyPositive(CertIdx idx, size_t expected);
+ void verifyNegative(CertIdx idx, int error = CKMC_ERROR_VERIFICATION_FAILED);
+
+private:
+ void addCert(ckmc_cert_list_s*& list, ckmc_cert_s* cert);
+ void addAlias(ckmc_alias_list_s*& list, const char* alias);
+
+ ckmc_cert_list_s* m_trustedCerts;
+ ckmc_alias_list_s* m_trustedAliases;
+
+ ckmc_cert_list_s* m_untrustedCerts;
+ ckmc_alias_list_s* m_untrustedAliases;
+
+ bool m_system;
+};
+
+template <typename T>
+ChainVerifier<T>::ChainVerifier() :
+ m_trustedCerts(NULL),
+ m_trustedAliases(NULL),
+ m_untrustedCerts(NULL),
+ m_untrustedAliases(NULL),
+ m_system(true)
+{
+}
+
+template <typename T>
+ChainVerifier<T>::~ChainVerifier()
+{
+ ckmc_cert_list_all_free(m_trustedCerts);
+ ckmc_cert_list_all_free(m_untrustedCerts);
+ ckmc_alias_list_all_free(m_trustedAliases);
+ ckmc_alias_list_all_free(m_untrustedAliases);
+}
+
+template <typename T>
+void ChainVerifier<T>::addTrusted(CertIdx idx)
+{
+ size_t size = list_size(m_trustedCerts);
+ ckmc_cert_s* cert = create_cert(idx);
+ addCert(m_trustedCerts, cert);
+
+ std::stringstream ss;
+ ss << "TRUSTED_CERT_ALIAS_" << size;
+ save_cert(cert, ss.str().c_str());
+ addAlias(m_trustedAliases, ss.str().c_str());
+}
+
+template <typename T>
+void ChainVerifier<T>::addUntrusted(CertIdx idx)
+{
+ size_t size = list_size(m_untrustedCerts);
+ ckmc_cert_s* cert = create_cert(idx);
+ addCert(m_untrustedCerts, cert);
+
+ std::stringstream ss;
+ ss << "UNTRUSTED_CERT_ALIAS_" << size;
+ save_cert(cert, ss.str().c_str());
+ addAlias(m_untrustedAliases, ss.str().c_str());
+}
+
+template <typename T>
+void ChainVerifier<T>::enableSystem(bool enable)
+{
+ m_system = enable;
+}
+
+template <typename T>
+void ChainVerifier<T>::addCert(ckmc_cert_list_s*& list, ckmc_cert_s* cert)
+{
+ if (!list) {
+ ckmc_cert_list_s* tmp = NULL;
+ assert_positive(ckmc_cert_list_new, cert, &tmp);
+ RUNNER_ASSERT_MSG_BT(!!tmp, "Cert list is NULL");
+ list = tmp;
+ } else {
+ ckmc_cert_list_s* last = list;
+ while(last->next)
+ last = last->next;
+ assert_positive(ckmc_cert_list_add, last, cert, &last);
+ RUNNER_ASSERT_MSG_BT(last != NULL, "Last cert on the list is NULL");
+ }
+}
+
+template <typename T>
+void ChainVerifier<T>::addAlias(ckmc_alias_list_s*& list, const char* alias)
+{
+ if (!list) {
+ ckmc_alias_list_s* tmp = NULL;
+ assert_positive(ckmc_alias_list_new, strdup(alias), &tmp);
+ RUNNER_ASSERT_MSG_BT(!!tmp, "Alias list is NULL");
+ list = tmp;
+ } else {
+ ckmc_alias_list_s* last = list;
+ while(last->next)
+ last = last->next;
+ assert_positive(ckmc_alias_list_add, last, strdup(alias), &last);
+ RUNNER_ASSERT_MSG_BT(last != NULL, "Last alias on the list is NULL");
+ }
+}
+
+template <typename T>
+void ChainVerifier<T>::verifyPositive(CertIdx idx, size_t expected)
+{
+ ckmc_cert_s* cert = create_cert(idx);
+
+ ckmc_cert_list_s* chain = NULL;
+
+ assert_positive(T::createChain,
+ cert,
+ m_untrustedCerts,
+ m_trustedCerts,
+ m_system,
+ &chain);
+
+ size_t size = list_size(chain);
+ ckmc_cert_list_all_free(chain);
+ chain = NULL;
+ RUNNER_ASSERT_MSG_BT(size == expected, "Expected chain size: " << expected << " got: " << size);
+
+ assert_positive(T::createChainWithAlias,
+ cert,
+ m_untrustedAliases,
+ m_trustedAliases,
+ m_system,
+ &chain);
+
+ size = list_size(chain);
+ ckmc_cert_list_all_free(chain);
+ chain = NULL;
+ RUNNER_ASSERT_MSG_BT(size == expected, "Expected chain size: " << expected << " got: " << size);
+ ckmc_cert_free(cert);
+}
+
+template <typename T>
+void ChainVerifier<T>::verifyNegative(CertIdx idx, int error)
+{
+ ckmc_cert_s* cert = create_cert(idx);
+
+ ckmc_cert_list_s* chain = NULL;
+
+ assert_result(error,
+ T::createChain,
+ cert,
+ m_untrustedCerts,
+ m_trustedCerts,
+ m_system,
+ &chain);
+ RUNNER_ASSERT_MSG_BT(chain == NULL, "Chain is not empty");
+
+ assert_result(error,
+ T::createChainWithAlias,
+ cert,
+ m_untrustedAliases,
+ m_trustedAliases,
+ m_system,
+ &chain);
+
+ RUNNER_ASSERT_MSG_BT(chain == NULL, "Chain is not empty");
+ ckmc_cert_free(cert);
+}
} // namespace anonymous
assert_positive(ckmc_unlock_user_key, 0, "test-pass");
}
-RUNNER_TEST(TCCH_0010_get_chain)
+// old API
+RUNNER_TEST(TCCH_0010_get_chain_old_api)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<ChainApiOld> cv;
+ cv.verifyNegative(CERT_LEAF);
+
+ cv.addUntrusted(CERT_IM_CA2);
+ cv.verifyPositive(CERT_LEAF, 3); // including system cert
+ cv.verifyNegative(CERT_TEST_LEAF);
+}
+
+// old API
+RUNNER_TEST(TCCH_0020_get_chain_old_api_system_only)
{
assert_positive(ckmc_remove_user_data,0);
- CertPtr cert_ee = create_cert(CERT_EE);
- CertPtr cert_im = create_cert(CERT_IM);
-
- CertListPtr untrusted = create_cert_list(cert_im.release(), NULL);
-
- // positive
- ckmc_cert_list_s* chain1 = NULL;
- assert_positive(ckmc_get_cert_chain, cert_ee.get(), untrusted.get(), &chain1);
- CertListPtr list1(chain1, ckmc_cert_list_all_free);
- assert_list_size(chain1, 3);
-
- // negative
- ckmc_cert_list_s* chain2 = NULL;
- assert_result(CKMC_ERROR_VERIFICATION_FAILED,
- ckmc_get_cert_chain,
- cert_ee.get(),
- NULL_CERTS,
- &chain2);
- CertListPtr list2(chain2, ckmc_cert_list_all_free);
- assert_list_size(chain2, 0);
+ ChainVerifier<ChainApiOld> cv;
+ cv.verifyPositive(CERT_IM_CA2, 2); // including system cert
}
-RUNNER_TEST(TCCH_0020_get_chain_with_alias)
+// check invalid arguments
+RUNNER_TEST(TCCH_0100_get_certificate_chain_invalid_param)
{
assert_positive(ckmc_remove_user_data,0);
- CertPtr cert_ee = create_cert(CERT_EE);
- CertPtr cert_im = create_cert(CERT_IM);
+ ckmc_cert_s* ca2 = create_cert(CERT_IM_CA2);
+ ckmc_cert_s* ca1 = create_cert(CERT_IM_CA1);
+ ckmc_cert_list_s* chain = NULL;
+
+ // cert
+ CertListPtr untrusted_c = create_cert_list(ca1, NULL);
+ ca1 = NULL;
+
+ assert_invalid_param(ckmc_get_certificate_chain,
+ NULL_CERT,
+ untrusted_c.get(),
+ untrusted_c.get(),
+ true,
+ &chain);
+
+ assert_invalid_param(ckmc_get_certificate_chain,
+ ca2,
+ untrusted_c.get(),
+ untrusted_c.get(),
+ true,
+ NULL_CHAIN);
+
+ // alias
+ ca1 = create_cert(CERT_IM_CA1);
+ save_cert(ca1, "CERT_IM_CA1");
+ AliasListPtr untrusted_a = create_alias_list("CERT_IM_CA1", NULL);
+
+ assert_invalid_param(ckmc_get_certificate_chain_with_alias,
+ NULL_CERT,
+ untrusted_a.get(),
+ untrusted_a.get(),
+ true,
+ &chain);
+
+ assert_invalid_param(ckmc_get_certificate_chain_with_alias,
+ ca2,
+ untrusted_a.get(),
+ untrusted_a.get(),
+ true,
+ NULL_CHAIN);
+
+ ckmc_cert_free(ca2);
+}
- save_cert(cert_im, "untrusted_certificate");
+// check invalid arguments
+RUNNER_TEST(TCCH_0110_get_certificate_chain_alias_unknown)
+{
+ assert_positive(ckmc_remove_user_data,0);
- AliasListPtr untrusted = create_alias_list("untrusted_certificate", NULL);
+ ckmc_cert_s* ca2 = create_cert(CERT_IM_CA2);
+ ckmc_cert_list_s* chain = NULL;
- // positive
- ckmc_cert_list_s* chain1 = NULL;
- assert_positive(ckmc_get_cert_chain_with_alias, cert_ee.get(), untrusted.get(), &chain1);
- CertListPtr list1(chain1, ckmc_cert_list_all_free);
- assert_list_size(chain1, 3);
+ AliasListPtr non_existing = create_alias_list("NON_EXISTING_ALIAS", NULL);
+ assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmc_get_certificate_chain_with_alias,
+ ca2,
+ non_existing.get(),
+ NULL_ALIASES,
+ true,
+ &chain);
- // negative
- ckmc_cert_list_s* chain2 = NULL;
- assert_result(CKMC_ERROR_VERIFICATION_FAILED,
- ckmc_get_cert_chain_with_alias,
- cert_ee.get(),
+ assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmc_get_certificate_chain_with_alias,
+ ca2,
NULL_ALIASES,
- &chain2);
- CertListPtr list2(chain2, ckmc_cert_list_all_free);
- assert_list_size(chain2, 0);
+ non_existing.get(),
+ true,
+ &chain);
+ ckmc_cert_free(ca2);
+}
+
+/*
+ * This test verifies that chain of trust won't be successfully built unless system or trusted
+ * certificates are used even if real trusted root ca certs are used as untrusted.
+ */
+RUNNER_TEST(TCCH_0120_get_certificate_chain_root_ca_negative)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.enableSystem(false);
+ cv.verifyNegative(CERT_ROOT_CA);
+
+ cv.addUntrusted(CERT_IM_CA2);
+ cv.verifyNegative(CERT_LEAF);
+}
+
+/*
+ * This test verifies that it's possible to build a chain of trust with single trusted certificate
+ * and no system certificates.
+ */
+RUNNER_TEST(TCCH_0140_get_certificate_chain_trusted_only)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.enableSystem(false);
+ cv.addTrusted(CERT_TEST_ROOT_CA);
+ cv.verifyPositive(CERT_TEST_IM_CA, 2);
+ cv.verifyNegative(CERT_TEST_LEAF);
+}
+
+/*
+ * This test verifies that it's possible to build a chain of trust with system certificates only
+ */
+RUNNER_TEST(TCCH_0150_get_certificate_chain_system_only)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.verifyPositive(CERT_IM_CA2, 2); // including system cert
+ cv.verifyNegative(CERT_LEAF);
+}
+
+/*
+ * Verifies that chain of trust can be built without untrusted certificates.
+ */
+RUNNER_TEST(TCCH_0160_get_certificate_chain_no_untrusted)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.addTrusted(CERT_TEST_ROOT_CA);
+ cv.verifyPositive(CERT_TEST_IM_CA, 2);// signed with trusted cert (CERT_TEST_ROOT_CA)
+ cv.verifyPositive(CERT_IM_CA2, 2); // signed with system cert (CERT_IM_CA1)
+ cv.verifyNegative(CERT_LEAF);
+}
+
+RUNNER_TEST(TCCH_0170_get_certificate_chain_no_trusted)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.addUntrusted(CERT_IM_CA2);
+ cv.verifyPositive(CERT_LEAF,3); // including system cert
+ cv.verifyNegative(CERT_TEST_LEAF);
+}
+
+/*
+ * Check if its possible to build a chain of trust without system certs.
+ */
+RUNNER_TEST(TCCH_0180_get_certificate_chain_no_system)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.enableSystem(false);
+ cv.addTrusted(CERT_TEST_ROOT_CA);
+ cv.addUntrusted(CERT_TEST_IM_CA);
+ cv.verifyPositive(CERT_TEST_LEAF, 3);
+ cv.verifyNegative(CERT_LEAF);
+}
+
+/*
+ * Check if its possible to build a chain of trust with intermediate ca cert in trusted list.
+ */
+RUNNER_TEST(TCCH_0190_get_certificate_chain_im_ca_in_trusted)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.enableSystem(false);
+ cv.addTrusted(CERT_TEST_ROOT_CA);
+ cv.addTrusted(CERT_TEST_IM_CA);
+ cv.verifyPositive(CERT_TEST_LEAF, 3);
+ cv.verifyNegative(CERT_LEAF);
+}
+
+RUNNER_TEST(TCCH_0200_get_certificate_chain_all)
+{
+ assert_positive(ckmc_remove_user_data,0);
+
+ ChainVerifier<> cv;
+ cv.enableSystem(true);
+ cv.addTrusted(CERT_TEST_ROOT_CA);
+ cv.addUntrusted(CERT_IM_CA1);
+ cv.addUntrusted(CERT_IM_CA2);
+ /*
+ * In combat conditions this may as well be 3. Because of 2 existing GeoTrust certificates with
+ * same Subject and Public key one being root ca and the other not there are 2 possible chains
+ * of trust for this certificate.
+ */
+ cv.verifyPositive(CERT_LEAF,4);
+ cv.verifyNegative(CERT_TEST_LEAF);
}
RUNNER_TEST(TCCH_9999_deinit)