blob: ebd8262d956329e3b40aa26a3daa2937430e728b [file] [log] [blame]
Adam Langley3a39b062016-01-14 14:08:58 -08001/* Copyright (c) 2016, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
David Benjamin750fea12018-12-05 13:12:48 -060015#include <algorithm>
Adam Langley1902d812018-03-23 11:40:45 -070016#include <functional>
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +020017#include <string>
Adam Langley3a39b062016-01-14 14:08:58 -080018#include <vector>
19
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +020020#include <gtest/gtest.h>
Adam Langley3a39b062016-01-14 14:08:58 -080021
David Benjamina4646742021-05-13 14:47:14 -040022#include <openssl/asn1.h>
Matthew Braithwaitee2c083d2017-01-06 13:35:32 -080023#include <openssl/bio.h>
Adam Langley48983312016-10-28 11:42:45 -070024#include <openssl/bytestring.h>
David Benjamin7c81c5f2022-12-29 14:13:24 -050025#include <openssl/conf.h>
David Benjamin93a69b42016-01-30 12:57:05 -050026#include <openssl/crypto.h>
David Benjaminae153bb2018-05-10 16:23:03 -040027#include <openssl/curve25519.h>
David Benjaminf0e935d2016-09-06 18:10:19 -040028#include <openssl/digest.h>
Adam Langley3a39b062016-01-14 14:08:58 -080029#include <openssl/err.h>
David Benjamina4646742021-05-13 14:47:14 -040030#include <openssl/nid.h>
Adam Langley3a39b062016-01-14 14:08:58 -080031#include <openssl/pem.h>
Adam Langley48983312016-10-28 11:42:45 -070032#include <openssl/pool.h>
David Benjamin93a69b42016-01-30 12:57:05 -050033#include <openssl/x509.h>
David Benjamin56aaf162017-11-24 12:36:51 -050034#include <openssl/x509v3.h>
Adam Langley3a39b062016-01-14 14:08:58 -080035
David Benjamindddb60e2021-08-11 01:23:09 -040036#include "internal.h"
David Benjamin17cf2cb2016-12-13 01:07:13 -050037#include "../internal.h"
David Benjaminae153bb2018-05-10 16:23:03 -040038#include "../test/test_util.h"
David Benjaminc67076d2019-04-16 17:39:50 -050039#include "../x509v3/internal.h"
David Benjamin17cf2cb2016-12-13 01:07:13 -050040
David Benjamin030693d2022-12-13 13:23:07 -050041#if defined(OPENSSL_THREADS)
42#include <thread>
43#endif
44
Adam Langley3a39b062016-01-14 14:08:58 -080045
David Benjamin40150002017-09-18 18:22:01 -040046std::string GetTestData(const char *path);
47
David Benjamin991835d2020-10-02 16:21:25 -040048static const char kCrossSigningRootPEM[] = R"(
49-----BEGIN CERTIFICATE-----
50MIICcTCCAdqgAwIBAgIIagJHiPvE0MowDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE
51ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v
52dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowPDEaMBgGA1UE
53ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v
54dCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwo3qFvSB9Zmlbpzn9wJp
55ikI75Rxkatez8VkLqyxbOhPYl2Haz8F5p1gDG96dCI6jcLGgu3AKT9uhEQyyUko5
56EKYasazSeA9CQrdyhPg0mkTYVETnPM1W/ebid1YtqQbq1CMWlq2aTDoSGAReGFKP
57RTdXAbuAXzpCfi/d8LqV13UCAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgIEMB0GA1Ud
58JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MBkGA1Ud
59DgQSBBBHKHC7V3Z/3oLvEZx0RZRwMBsGA1UdIwQUMBKAEEcocLtXdn/egu8RnHRF
60lHAwDQYJKoZIhvcNAQELBQADgYEAnglibsy6mGtpIXivtlcz4zIEnHw/lNW+r/eC
61CY7evZTmOoOuC/x9SS3MF9vawt1HFUummWM6ZgErqVBOXIB4//ykrcCgf5ZbF5Hr
62+3EFprKhBqYiXdD8hpBkrBoXwn85LPYWNd2TceCrx0YtLIprE2R5MB2RIq8y4Jk3
63YFXvkME=
64-----END CERTIFICATE-----
65)";
Adam Langley3a39b062016-01-14 14:08:58 -080066
David Benjamin991835d2020-10-02 16:21:25 -040067static const char kRootCAPEM[] = R"(
68-----BEGIN CERTIFICATE-----
69MIICVTCCAb6gAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwLjEaMBgGA1UE
70ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwIBcNMTUwMTAx
71MDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMC4xGjAYBgNVBAoTEUJvcmluZ1NTTCBU
72RVNUSU5HMRAwDgYDVQQDEwdSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
73iQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM
742uCFETXCknJJjYG0iJdrt/yyRFvZTQZw+QzGj+mz36NqhGxDWb6dstB2m8PX+plZ
75w7jl81MDvUnWs8yiQ/6twgu5AbhWKZQDJKcNKCEpqa6UW0r5nwIDAQABo3oweDAO
76BgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8G
77A1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEEA31wH7QC+4HH5UBCeMWQEwGwYDVR0j
78BBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOBgQDXylEK77Za
79kKeY6ZerrScWyZhrjIGtHFu09qVpdJEzrk87k2G7iHHR9CAvSofCgEExKtWNS9dN
80+9WiZp/U48iHLk7qaYXdEuO07No4BYtXn+lkOykE+FUxmA4wvOF1cTd2tdj3MzX2
81kfGIBAYhzGZWhY3JbhIfTEfY1PNM1pWChQ==
82-----END CERTIFICATE-----
83)";
Adam Langley3a39b062016-01-14 14:08:58 -080084
David Benjamin991835d2020-10-02 16:21:25 -040085static const char kRootCrossSignedPEM[] = R"(
86-----BEGIN CERTIFICATE-----
87MIICYzCCAcygAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE
88ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v
89dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowLjEaMBgGA1UE
90ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwgZ8wDQYJKoZI
91hvcNAQEBBQADgY0AMIGJAoGBAOkOfxEM5lrmhoNw9lEHLgJ4EfWyJJI47iZiAseU
928T6hd2rAj9UiaLZd4kza4IURNcKSckmNgbSIl2u3/LJEW9lNBnD5DMaP6bPfo2qE
93bENZvp2y0Habw9f6mVnDuOXzUwO9SdazzKJD/q3CC7kBuFYplAMkpw0oISmprpRb
94SvmfAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEFBQcD
95AQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gc
96flQEJ4xZATAbBgNVHSMEFDASgBBHKHC7V3Z/3oLvEZx0RZRwMA0GCSqGSIb3DQEB
97CwUAA4GBAErTxYJ0en9HVRHAAr5OO5wuk5Iq3VMc79TMyQLCXVL8YH8Uk7KEwv+q
989MEKZv2eR/Vfm4HlXlUuIqfgUXbwrAYC/YVVX86Wnbpy/jc73NYVCq8FEZeO+0XU
9990SWAPDdp+iL7aZdimnMtG1qlM1edmz8AKbrhN/R3IbA2CL0nCWV
100-----END CERTIFICATE-----
101)";
Adam Langley3a39b062016-01-14 14:08:58 -0800102
David Benjamin991835d2020-10-02 16:21:25 -0400103static const char kIntermediatePEM[] = R"(
104-----BEGIN CERTIFICATE-----
105MIICXjCCAcegAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMC4xGjAYBgNV
106BAoTEUJvcmluZ1NTTCBURVNUSU5HMRAwDgYDVQQDEwdSb290IENBMCAXDTE1MDEw
107MTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjA2MRowGAYDVQQKExFCb3JpbmdTU0wg
108VEVTVElORzEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIGfMA0GCSqGSIb3DQEB
109AQUAA4GNADCBiQKBgQC7YtI0l8ocTYJ0gKyXTtPL4iMJCNY4OcxXl48jkncVG1Hl
110blicgNUa1r9m9YFtVkxvBinb8dXiUpEGhVg4awRPDcatlsBSEBuJkiZGYbRcAmSu
111CmZYnf6u3aYQ18SU8WqVERPpE4cwVVs+6kwlzRw0+XDoZAczu8ZezVhCUc6NbQID
112AQABo3oweDAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
113AQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEIwaaKi1dttdV3sfjRSy
114BqMwGwYDVR0jBBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOB
115gQCvnolNWEHuQS8PFVVyuLR+FKBeUUdrVbSfHSzTqNAqQGp0C9fk5oCzDq6ZgTfY
116ESXM4cJhb3IAnW0UM0NFsYSKQJ50JZL2L3z5ZLQhHdbs4RmODGoC40BVdnJ4/qgB
117aGSh09eQRvAVmbVCviDK2ipkWNegdyI19jFfNP5uIkGlYg==
118-----END CERTIFICATE-----
119)";
Adam Langley3a39b062016-01-14 14:08:58 -0800120
David Benjamin991835d2020-10-02 16:21:25 -0400121static const char kIntermediateSelfSignedPEM[] = R"(
122-----BEGIN CERTIFICATE-----
123MIICZjCCAc+gAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV
124BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew
125IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDYxGjAYBgNVBAoTEUJv
126cmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0EwgZ8wDQYJ
127KoZIhvcNAQEBBQADgY0AMIGJAoGBALti0jSXyhxNgnSArJdO08viIwkI1jg5zFeX
128jyOSdxUbUeVuWJyA1RrWv2b1gW1WTG8GKdvx1eJSkQaFWDhrBE8Nxq2WwFIQG4mS
129JkZhtFwCZK4KZlid/q7dphDXxJTxapURE+kThzBVWz7qTCXNHDT5cOhkBzO7xl7N
130WEJRzo1tAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEF
131BQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQjBpoqLV2
132211Xex+NFLIGozAbBgNVHSMEFDASgBCMGmiotXbbXVd7H40UsgajMA0GCSqGSIb3
133DQEBCwUAA4GBALcccSrAQ0/EqQBsx0ZDTUydHXXNP2DrUkpUKmAXIe8McqIVSlkT
1346H4xz7z8VRKBo9j+drjjtCw2i0CQc8aOLxRb5WJ8eVLnaW2XRlUqAzhF0CrulfVI
135E4Vs6ZLU+fra1WAuIj6qFiigRja+3YkZArG8tMA9vtlhTX/g7YBZIkqH
136-----END CERTIFICATE-----
137)";
Adam Langley3a39b062016-01-14 14:08:58 -0800138
David Benjamin991835d2020-10-02 16:21:25 -0400139static const char kLeafPEM[] = R"(
140-----BEGIN CERTIFICATE-----
141MIICXjCCAcegAwIBAgIIWjO48ufpunYwDQYJKoZIhvcNAQELBQAwNjEaMBgGA1UE
142ChMRQm9yaW5nU1NMIFRFU1RJTkcxGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAg
143Fw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowMjEaMBgGA1UEChMRQm9y
144aW5nU1NMIFRFU1RJTkcxFDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3
145DQEBAQUAA4GNADCBiQKBgQDD0U0ZYgqShJ7oOjsyNKyVXEHqeafmk/bAoPqY/h1c
146oPw2E8KmeqiUSoTPjG5IXSblOxcqpbAXgnjPzo8DI3GNMhAf8SYNYsoH7gc7Uy7j
1475x8bUrisGnuTHqkqH6d4/e7ETJ7i3CpR8bvK16DggEvQTudLipz8FBHtYhFakfdh
148TwIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
149CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEKN5pvbur7mlXjeMEYA0
1504nUwGwYDVR0jBBQwEoAQjBpoqLV2211Xex+NFLIGozANBgkqhkiG9w0BAQsFAAOB
151gQBj/p+JChp//LnXWC1k121LM/ii7hFzQzMrt70bny406SGz9jAjaPOX4S3gt38y
152rhjpPukBlSzgQXFg66y6q5qp1nQTD1Cw6NkKBe9WuBlY3iYfmsf7WT8nhlT1CttU
153xNCwyMX9mtdXdQicOfNjIGUCD5OLV5PgHFPRKiHHioBAhg==
154-----END CERTIFICATE-----
155)";
Adam Langley3a39b062016-01-14 14:08:58 -0800156
David Benjamin991835d2020-10-02 16:21:25 -0400157static const char kLeafNoKeyUsagePEM[] = R"(
158-----BEGIN CERTIFICATE-----
159MIICNTCCAZ6gAwIBAgIJAIFQGaLQ0G2mMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV
160BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew
161IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDcxGjAYBgNVBAoTEUJv
162cmluZ1NTTCBURVNUSU5HMRkwFwYDVQQDExBldmlsLmV4YW1wbGUuY29tMIGfMA0G
163CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOKoZe75NPz77EOaMMl4/0s3PyQw++zJvp
164ejHAxZiTPCJgMbEHLrSzNoHdopg+CLUH5bE4wTXM8w9Inv5P8OAFJt7gJuPUunmk
165j+NoU3QfzOR6BroePcz1vXX9jyVHRs087M/sLqWRHu9IR+/A+UTcBaWaFiDVUxtJ
166YOwFMwjNPQIDAQABo0gwRjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBJfLEUWHq1
16727rZ1AVx2J5GMBsGA1UdIwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwDQYJKoZIhvcN
168AQELBQADgYEALVKN2Y3LZJOtu6SxFIYKxbLaXhTGTdIjxipZhmbBRDFjbZjZZOTe
1696Oo+VDNPYco4rBexK7umYXJyfTqoY0E8dbiImhTcGTEj7OAB3DbBomgU1AYe+t2D
170uwBqh4Y3Eto+Zn4pMVsxGEfUpjzjZDel7bN1/oU/9KWPpDfywfUmjgk=
171-----END CERTIFICATE-----
172)";
Adam Langley3a39b062016-01-14 14:08:58 -0800173
David Benjamin991835d2020-10-02 16:21:25 -0400174static const char kForgeryPEM[] = R"(
175-----BEGIN CERTIFICATE-----
176MIICZzCCAdCgAwIBAgIIdTlMzQoKkeMwDQYJKoZIhvcNAQELBQAwNzEaMBgGA1UE
177ChMRQm9yaW5nU1NMIFRFU1RJTkcxGTAXBgNVBAMTEGV2aWwuZXhhbXBsZS5jb20w
178IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDoxGjAYBgNVBAoTEUJv
179cmluZ1NTTCBURVNUSU5HMRwwGgYDVQQDExNmb3JnZXJ5LmV4YW1wbGUuY29tMIGf
180MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDADTwruBQZGb7Ay6s9HiYv5d1lwtEy
181xQdA2Sy8Rn8uA20Q4KgqwVY7wzIZ+z5Butrsmwb70gdG1XU+yRaDeE7XVoW6jSpm
1820sw35/5vJbTcL4THEFbnX0OPZnvpuZDFUkvVtq5kxpDWsVyM24G8EEq7kPih3Sa3
183OMhXVXF8kso6UQIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI
184KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEEYJ/WHM
1858p64erPWIg4/liwwGwYDVR0jBBQwEoAQSXyxFFh6tdu62dQFcdieRjANBgkqhkiG
1869w0BAQsFAAOBgQA+zH7bHPElWRWJvjxDqRexmYLn+D3Aivs8XgXQJsM94W0EzSUf
187DSLfRgaQwcb2gg2xpDFoG+W0vc6O651uF23WGt5JaFFJJxqjII05IexfCNhuPmp4
1884UZAXPttuJXpn74IY1tuouaM06B3vXKZR+/ityKmfJvSwxacmFcK+2ziAg==
189-----END CERTIFICATE-----
190)";
Adam Langley3a39b062016-01-14 14:08:58 -0800191
David Benjamin93a69b42016-01-30 12:57:05 -0500192// kBadPSSCertPEM is a self-signed RSA-PSS certificate with bad parameters.
David Benjamin991835d2020-10-02 16:21:25 -0400193static const char kBadPSSCertPEM[] = R"(
194-----BEGIN CERTIFICATE-----
195MIIDdjCCAjqgAwIBAgIJANcwZLyfEv7DMD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI
196AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3jAnMSUwIwYD
197VQQDDBxUZXN0IEludmFsaWQgUFNTIGNlcnRpZmljYXRlMB4XDTE1MTEwNDE2MDIz
198NVoXDTE1MTIwNDE2MDIzNVowJzElMCMGA1UEAwwcVGVzdCBJbnZhbGlkIFBTUyBj
199ZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTaM7WH
200qVCAGAIA+zL1KWvvASTrhlq+1ePdO7wsrWX2KiYoTYrJYTnxhLnn0wrHqApt79nL
201IBG7cfShyZqFHOY/IzlYPMVt+gPo293gw96Fds5JBsjhjkyGnOyr9OUntFqvxDbT
202IIFU7o9IdxD4edaqjRv+fegVE+B79pDk4s0ujsk6dULtCg9Rst0ucGFo19mr+b7k
203dbfn8pZ72ZNDJPueVdrUAWw9oll61UcYfk75XdrLk6JlL41GrYHc8KlfXf43gGQq
204QfrpHkg4Ih2cI6Wt2nhFGAzrlcorzLliQIUJRIhM8h4IgDfpBpaPdVQLqS2pFbXa
2055eQjqiyJwak2vJ8CAwEAAaNQME4wHQYDVR0OBBYEFCt180N4oGUt5LbzBwQ4Ia+2
2064V97MB8GA1UdIwQYMBaAFCt180N4oGUt5LbzBwQ4Ia+24V97MAwGA1UdEwQFMAMB
207Af8wMQYJKoZIhvcNAQEKMCSgDTALBglghkgBZQMEAgGhDTALBgkqhkiG9w0BAQii
208BAICAN4DggEBAAjBtm90lGxgddjc4Xu/nbXXFHVs2zVcHv/mqOZoQkGB9r/BVgLb
209xhHrFZ2pHGElbUYPfifdS9ztB73e1d4J+P29o0yBqfd4/wGAc/JA8qgn6AAEO/Xn
210plhFeTRJQtLZVl75CkHXgUGUd3h+ADvKtcBuW9dSUncaUrgNKR8u/h/2sMG38RWY
211DzBddC/66YTa3r7KkVUfW7yqRQfELiGKdcm+bjlTEMsvS+EhHup9CzbpoCx2Fx9p
212NPtFY3yEObQhmL1JyoCRWqBE75GzFPbRaiux5UpEkns+i3trkGssZzsOuVqHNTNZ
213lC9+9hPHIoc9UMmAQNo1vGIW3NWVoeGbaJ8=
214-----END CERTIFICATE-----
215)";
David Benjamin93a69b42016-01-30 12:57:05 -0500216
David Benjamin991835d2020-10-02 16:21:25 -0400217static const char kRSAKey[] = R"(
218-----BEGIN RSA PRIVATE KEY-----
219MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92
220kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF
221KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB
222AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe
223i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+
224WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ
225m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj
226QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk
227aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj
228LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk
229104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/
230tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd
231moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==
232-----END RSA PRIVATE KEY-----
233)";
David Benjamin93a69b42016-01-30 12:57:05 -0500234
David Benjamin40f49422020-10-23 11:08:41 -0400235static const char kP256Key[] = R"(
236-----BEGIN PRIVATE KEY-----
237MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBw8IcnrUoEqc3VnJ
238TYlodwi1b8ldMHcO6NHJzgqLtGqhRANCAATmK2niv2Wfl74vHg2UikzVl2u3qR4N
239Rvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYaHPUdfvGULUvPciLB
240-----END PRIVATE KEY-----
241)";
242
David Benjamina1bbaca2016-10-25 18:51:20 -0400243// kCRLTestRoot is a test root certificate. It has private key:
244//
245// -----BEGIN RSA PRIVATE KEY-----
246// MIIEpAIBAAKCAQEAo16WiLWZuaymsD8n5SKPmxV1y6jjgr3BS/dUBpbrzd1aeFzN
247// lI8l2jfAnzUyp+I21RQ+nh/MhqjGElkTtK9xMn1Y+S9GMRh+5R/Du0iCb1tCZIPY
248// 07Tgrb0KMNWe0v2QKVVruuYSgxIWodBfxlKO64Z8AJ5IbnWpuRqO6rctN9qUoMlT
249// IAB6dL4G0tDJ/PGFWOJYwOMEIX54bly2wgyYJVBKiRRt4f7n8H922qmvPNA9idmX
250// 9G1VAtgV6x97XXi7ULORIQvn9lVQF6nTYDBJhyuPB+mLThbLP2o9orxGx7aCtnnB
251// ZUIxUvHNOI0FaSaZH7Fi0xsZ/GkG2HZe7ImPJwIDAQABAoIBAQCJF9MTHfHGkk+/
252// DwCXlA0Wg0e6hBuHl10iNobYkMWIl/xXjOknhYiqOqb181py76472SVC5ERprC+r
253// Lf0PXzqKuA117mnkwT2bYLCL9Skf8WEhoFLQNbVlloF6wYjqXcYgKYKh8HgQbZl4
254// aLg2YQl2NADTNABsUWj/4H2WEelsODVviqfFs725lFg9KHDI8zxAZXLzDt/M9uVL
255// GxJiX12tr0AwaeAFZ1oPM/y+LznM3N3+Ht3jHHw3jZ/u8Z1RdAmdpu3bZ6tbwGBr
256// 9edsH5rKkm9aBvMrY7eX5VHqaqyRNFyG152ZOJh4XiiFG7EmgTPCpaHo50Y018Re
257// grVtk+FBAoGBANY3lY+V8ZOwMxSHes+kTnoimHO5Ob7nxrOC71i27x+4HHsYUeAr
258// /zOOghiDIn+oNkuiX5CIOWZKx159Bp65CPpCbTb/fh+HYnSgXFgCw7XptycO7LXM
259// 5GwR5jSfpfzBFdYxjxoUzDMFBwTEYRTm0HkUHkH+s+ajjw5wqqbcGLcfAoGBAMM8
260// DKW6Tb66xsf708f0jonAjKYTLZ+WOcwsBEWSFHoY8dUjvW5gqx5acHTEsc5ZTeh4
261// BCFLa+Mn9cuJWVJNs09k7Xb2PNl92HQ4GN2vbdkJhExbkT6oLDHg1hVD0w8KLfz1
262// lTAW6pS+6CdOHMEJpvqx89EgU/1GgIQ1fXYczE75AoGAKeJoXdDFkUjsU+FBhAPu
263// TDcjc80Nm2QaF9NMFR5/lsYa236f06MGnQAKM9zADBHJu/Qdl1brUjLg1HrBppsr
264// RDNkw1IlSOjhuUf5hkPUHGd8Jijm440SRIcjabqla8wdBupdvo2+d2NOQgJbsQiI
265// ToQ+fkzcxAXK3Nnuo/1436UCgYBjLH7UNOZHS8OsVM0I1r8NVKVdu4JCfeJQR8/H
266// s2P5ffBir+wLRMnH+nMDreMQiibcPxMCArkERAlE4jlgaJ38Z62E76KLbLTmnJRt
267// EC9Bv+bXjvAiHvWMRMUbOj/ddPNVez7Uld+FvdBaHwDWQlvzHzBWfBCOKSEhh7Z6
268// qDhUqQKBgQDPMDx2i5rfmQp3imV9xUcCkIRsyYQVf8Eo7NV07IdUy/otmksgn4Zt
269// Lbf3v2dvxOpTNTONWjp2c+iUQo8QxJCZr5Sfb21oQ9Ktcrmc/CY7LeBVDibXwxdM
270// vRG8kBzvslFWh7REzC3u06GSVhyKDfW93kN2cKVwGoahRlhj7oHuZQ==
271// -----END RSA PRIVATE KEY-----
David Benjamin991835d2020-10-02 16:21:25 -0400272static const char kCRLTestRoot[] = R"(
273-----BEGIN CERTIFICATE-----
274MIIDbzCCAlegAwIBAgIJAODri7v0dDUFMA0GCSqGSIb3DQEBCwUAME4xCzAJBgNV
275BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
276aWV3MRIwEAYDVQQKDAlCb3JpbmdTU0wwHhcNMTYwOTI2MTUwNjI2WhcNMjYwOTI0
277MTUwNjI2WjBOMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
278A1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJQm9yaW5nU1NMMIIBIjANBgkq
279hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo16WiLWZuaymsD8n5SKPmxV1y6jjgr3B
280S/dUBpbrzd1aeFzNlI8l2jfAnzUyp+I21RQ+nh/MhqjGElkTtK9xMn1Y+S9GMRh+
2815R/Du0iCb1tCZIPY07Tgrb0KMNWe0v2QKVVruuYSgxIWodBfxlKO64Z8AJ5IbnWp
282uRqO6rctN9qUoMlTIAB6dL4G0tDJ/PGFWOJYwOMEIX54bly2wgyYJVBKiRRt4f7n
2838H922qmvPNA9idmX9G1VAtgV6x97XXi7ULORIQvn9lVQF6nTYDBJhyuPB+mLThbL
284P2o9orxGx7aCtnnBZUIxUvHNOI0FaSaZH7Fi0xsZ/GkG2HZe7ImPJwIDAQABo1Aw
285TjAdBgNVHQ4EFgQUWPt3N5cZ/CRvubbrkqfBnAqhq94wHwYDVR0jBBgwFoAUWPt3
286N5cZ/CRvubbrkqfBnAqhq94wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
287AQEAORu6M0MOwXy+3VEBwNilfTxyqDfruQsc1jA4PT8Oe8zora1WxE1JB4q2FJOz
288EAuM3H/NXvEnBuN+ITvKZAJUfm4NKX97qmjMJwLKWe1gVv+VQTr63aR7mgWJReQN
289XdMztlVeZs2dppV6uEg3ia1X0G7LARxGpA9ETbMyCpb39XxlYuTClcbA5ftDN99B
2903Xg9KNdd++Ew22O3HWRDvdDpTO/JkzQfzi3sYwUtzMEonENhczJhGf7bQMmvL/w5
29124Wxj4Z7KzzWIHsNqE/RIs6RV3fcW61j/mRgW2XyoWnMVeBzvcJr9NXp4VQYmFPw
292amd8GKMZQvP0ufGnUn7D7uartA==
293-----END CERTIFICATE-----
294)";
Steven Valdezf9f312a2016-09-26 11:41:04 -0400295
David Benjamin991835d2020-10-02 16:21:25 -0400296static const char kCRLTestLeaf[] = R"(
297-----BEGIN CERTIFICATE-----
298MIIDkDCCAnigAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMx
299EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEjAQ
300BgNVBAoMCUJvcmluZ1NTTDAeFw0xNjA5MjYxNTA4MzFaFw0xNzA5MjYxNTA4MzFa
301MEsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQKDAlC
302b3JpbmdTU0wxEzARBgNVBAMMCmJvcmluZy5zc2wwggEiMA0GCSqGSIb3DQEBAQUA
303A4IBDwAwggEKAoIBAQDc5v1S1M0W+QWM+raWfO0LH8uvqEwuJQgODqMaGnSlWUx9
3048iQcnWfjyPja3lWg9K62hSOFDuSyEkysKHDxijz5R93CfLcfnVXjWQDJe7EJTTDP
305ozEvxN6RjAeYv7CF000euYr3QT5iyBjg76+bon1p0jHZBJeNPP1KqGYgyxp+hzpx
306e0gZmTlGAXd8JQK4v8kpdYwD6PPifFL/jpmQpqOtQmH/6zcLjY4ojmqpEdBqIKIX
307+saA29hMq0+NK3K+wgg31RU+cVWxu3tLOIiesETkeDgArjWRS1Vkzbi4v9SJxtNu
308OZuAxWiynRJw3JwH/OFHYZIvQqz68ZBoj96cepjPAgMBAAGjezB5MAkGA1UdEwQC
309MAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl
310MB0GA1UdDgQWBBTGn0OVVh/aoYt0bvEKG+PIERqnDzAfBgNVHSMEGDAWgBRY+3c3
311lxn8JG+5tuuSp8GcCqGr3jANBgkqhkiG9w0BAQsFAAOCAQEAd2nM8gCQN2Dc8QJw
312XSZXyuI3DBGGCHcay/3iXu0JvTC3EiQo8J6Djv7WLI0N5KH8mkm40u89fJAB2lLZ
313ShuHVtcC182bOKnePgwp9CNwQ21p0rDEu/P3X46ZvFgdxx82E9xLa0tBB8PiPDWh
314lV16jbaKTgX5AZqjnsyjR5o9/mbZVupZJXx5Syq+XA8qiJfstSYJs4KyKK9UOjql
315ICkJVKpi2ahDBqX4MOH4SLfzVk8pqSpviS6yaA1RXqjpkxiN45WWaXDldVHMSkhC
3165CNXsXi4b1nAntu89crwSLA3rEwzCWeYj+BX7e1T9rr3oJdwOU/2KQtW1js1yQUG
317tjJMFw==
318-----END CERTIFICATE-----
319)";
Steven Valdezf9f312a2016-09-26 11:41:04 -0400320
David Benjamin991835d2020-10-02 16:21:25 -0400321static const char kBasicCRL[] = R"(
322-----BEGIN X509 CRL-----
323MIIBpzCBkAIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
324CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
325Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoA4wDDAKBgNV
326HRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAnrBKKgvd9x9zwK9rtUvVeFeJ7+LN
327ZEAc+a5oxpPNEsJx6hXoApYEbzXMxuWBQoCs5iEBycSGudct21L+MVf27M38KrWo
328eOkq0a2siqViQZO2Fb/SUFR0k9zb8xl86Zf65lgPplALun0bV/HT7MJcl04Tc4os
329dsAReBs5nqTGNEd5AlC1iKHvQZkM//MD51DspKnDpsDiUVi54h9C1SpfZmX8H2Vv
330diyu0fZ/bPAM3VAGawatf/SyWfBMyKpoPXEG39oAzmjjOj8en82psn7m474IGaho
331/vBbhl1ms5qQiLYPjm4YELtnXQoFyC72tBjbdFd/ZE9k4CNKDbxFUXFbkw==
332-----END X509 CRL-----
333)";
Steven Valdezf9f312a2016-09-26 11:41:04 -0400334
David Benjamin991835d2020-10-02 16:21:25 -0400335static const char kRevokedCRL[] = R"(
336-----BEGIN X509 CRL-----
337MIIBvjCBpwIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
338CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
339Qm9yaW5nU1NMFw0xNjA5MjYxNTEyNDRaFw0xNjEwMjYxNTEyNDRaMBUwEwICEAAX
340DTE2MDkyNjE1MTIyNlqgDjAMMAoGA1UdFAQDAgECMA0GCSqGSIb3DQEBCwUAA4IB
341AQCUGaM4DcWzlQKrcZvI8TMeR8BpsvQeo5BoI/XZu2a8h//PyRyMwYeaOM+3zl0d
342sjgCT8b3C1FPgT+P2Lkowv7rJ+FHJRNQkogr+RuqCSPTq65ha4WKlRGWkMFybzVH
343NloxC+aU3lgp/NlX9yUtfqYmJek1CDrOOGPrAEAwj1l/BUeYKNGqfBWYJQtPJu+5
344OaSvIYGpETCZJscUWODmLEb/O3DM438vLvxonwGqXqS0KX37+CHpUlyhnSovxXxp
345Pz4aF+L7OtczxL0GYtD2fR9B7TDMqsNmHXgQrixvvOY7MUdLGbd4RfJL3yA53hyO
346xzfKY2TzxLiOmctG0hXFkH5J
347-----END X509 CRL-----
348)";
Steven Valdezf9f312a2016-09-26 11:41:04 -0400349
David Benjamin991835d2020-10-02 16:21:25 -0400350static const char kBadIssuerCRL[] = R"(
351-----BEGIN X509 CRL-----
352MIIBwjCBqwIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzETMBEGA1UE
353CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEWMBQGA1UECgwN
354Tm90IEJvcmluZ1NTTBcNMTYwOTI2MTUxMjQ0WhcNMTYxMDI2MTUxMjQ0WjAVMBMC
355AhAAFw0xNjA5MjYxNTEyMjZaoA4wDDAKBgNVHRQEAwIBAjANBgkqhkiG9w0BAQsF
356AAOCAQEAlBmjOA3Fs5UCq3GbyPEzHkfAabL0HqOQaCP12btmvIf/z8kcjMGHmjjP
357t85dHbI4Ak/G9wtRT4E/j9i5KML+6yfhRyUTUJKIK/kbqgkj06uuYWuFipURlpDB
358cm81RzZaMQvmlN5YKfzZV/clLX6mJiXpNQg6zjhj6wBAMI9ZfwVHmCjRqnwVmCUL
359TybvuTmkryGBqREwmSbHFFjg5ixG/ztwzON/Ly78aJ8Bql6ktCl9+/gh6VJcoZ0q
360L8V8aT8+Ghfi+zrXM8S9BmLQ9n0fQe0wzKrDZh14EK4sb7zmOzFHSxm3eEXyS98g
361Od4cjsc3ymNk88S4jpnLRtIVxZB+SQ==
362-----END X509 CRL-----
363)";
David Benjaminbe941d42016-10-22 13:55:05 -0400364
365// kKnownCriticalCRL is kBasicCRL but with a critical issuing distribution point
366// extension.
David Benjamin991835d2020-10-02 16:21:25 -0400367static const char kKnownCriticalCRL[] = R"(
368-----BEGIN X509 CRL-----
369MIIBuDCBoQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
370CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
371Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoB8wHTAKBgNV
372HRQEAwIBATAPBgNVHRwBAf8EBTADgQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAs37Jq
3733Htcehm6C2PKXOHekwTqTLOPWsYHfF68kYhdzcopDZBeoKE7jLRkRRGFDaR/tfUs
374kwLSDNSQ8EwPb9PT1X8kmFn9QmJgWD6f6BzaH5ZZ9iBUwOcvrydlb/jnjdIZHQxs
375fKOAceW5XX3f7DANC3qwYLsQZR/APkfV8nXjPYVUz1kKj04uq/BbQviInjyUYixN
376xDx+GDWVVXccehcwAu983kAqP+JDaVQPBVksLuBXz2adrEWwvbLCnZeL3zH1IY9h
3776MFO6echpvGbU/H+dRX9UkhdJ7gdwKVD3RjfJl+DRVox9lz8Pbo5H699Tkv9/DQP
3789dMWxqhQlv23osLp
379-----END X509 CRL-----
380)";
David Benjaminbe941d42016-10-22 13:55:05 -0400381
382// kUnknownCriticalCRL is kBasicCRL but with an unknown critical extension.
David Benjamin991835d2020-10-02 16:21:25 -0400383static const char kUnknownCriticalCRL[] = R"(
384-----BEGIN X509 CRL-----
385MIIBvDCBpQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
386CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
387Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoCMwITAKBgNV
388HRQEAwIBATATBgwqhkiG9xIEAYS3CQABAf8EADANBgkqhkiG9w0BAQsFAAOCAQEA
389GvBP0xqL509InMj/3493YVRV+ldTpBv5uTD6jewzf5XdaxEQ/VjTNe5zKnxbpAib
390Kf7cwX0PMSkZjx7k7kKdDlEucwVvDoqC+O9aJcqVmM6GDyNb9xENxd0XCXja6MZC
391yVgP4AwLauB2vSiEprYJyI1APph3iAEeDm60lTXX/wBM/tupQDDujKh2GPyvBRfJ
392+wEDwGg3ICwvu4gO4zeC5qnFR+bpL9t5tOMAQnVZ0NWv+k7mkd2LbHdD44dxrfXC
393nhtfERx99SDmC/jtUAJrGhtCO8acr7exCeYcduN7KKCm91OeCJKK6OzWst0Og1DB
394kwzzU2rL3G65CrZ7H0SZsQ==
395-----END X509 CRL-----
396)";
David Benjaminbe941d42016-10-22 13:55:05 -0400397
398// kUnknownCriticalCRL2 is kBasicCRL but with a critical issuing distribution
399// point extension followed by an unknown critical extension
David Benjamin991835d2020-10-02 16:21:25 -0400400static const char kUnknownCriticalCRL2[] = R"(
401-----BEGIN X509 CRL-----
402MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
403CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
404Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoDQwMjAKBgNV
405HRQEAwIBATAPBgNVHRwBAf8EBTADgQH/MBMGDCqGSIb3EgQBhLcJAAEB/wQAMA0G
406CSqGSIb3DQEBCwUAA4IBAQBgSogsC5kf2wzr+0hmZtmLXYd0itAiYO0Gh9AyaEOO
407myJFuqICHBSLXXUgwNkTUa2x2I/ivyReVFV756VOlWoaV2wJUs0zeCeVBgC9ZFsq
4085a+8OGgXwgoYESFV5Y3QRF2a1Ytzfbw/o6xLXzTngvMsLOs12D4B5SkopyEZibF4
409tXlRZyvEudTg3CCrjNP+p/GV07nZ3wcMmKJwQeilgzFUV7NaVCCo9jvPBGp0RxAN
410KNif7jmjK4hD5mswo/Eq5kxQIc+mTfuUFdgHuAu1hfLYe0YK+Hr4RFf6Qy4hl7Ne
411YjqkkSVIcr87u+8AznwdstnQzsyD27Jt7SjVORkYRywi
412-----END X509 CRL-----
413)";
David Benjaminfd86eaa2020-06-17 15:13:16 -0400414
415// kBadExtensionCRL is kBasicCRL but with an incorrectly-encoded issuing
416// distribution point extension.
David Benjamin991835d2020-10-02 16:21:25 -0400417static const char kBadExtensionCRL[] = R"(
418-----BEGIN X509 CRL-----
419MIIBujCBowIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
420CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
421Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoCEwHzAKBgNV
422HRQEAwIBATARBgNVHRwBAf8EBzAFoQMBAf8wDQYJKoZIhvcNAQELBQADggEBAA+3
423i+5e5Ub8sccfgOBs6WVJFI9c8gvJjrJ8/dYfFIAuCyeocs7DFXn1n13CRZ+URR/Q
424mVWgU28+xeusuSPYFpd9cyYTcVyNUGNTI3lwgcE/yVjPaOmzSZKdPakApRxtpKKQ
425NN/56aQz3bnT/ZSHQNciRB8U6jiD9V30t0w+FDTpGaG+7bzzUH3UVF9xf9Ctp60A
4263mfLe0scas7owSt4AEFuj2SPvcE7yvdOXbu+IEv21cEJUVExJAbhvIweHXh6yRW+
4277VVeiNzdIjkZjyTmAzoXGha4+wbxXyBRbfH+XWcO/H+8nwyG8Gktdu2QB9S9nnIp
428o/1TpfOMSGhMyMoyPrk=
429-----END X509 CRL-----
430)";
Steven Valdezf9f312a2016-09-26 11:41:04 -0400431
David Benjamineb5640b2021-02-26 01:14:47 -0500432// kAlgorithmMismatchCRL is kBasicCRL but with mismatched AlgorithmIdentifiers
433// in the outer structure and signed portion. The signature reflects the signed
434// portion.
435static const char kAlgorithmMismatchCRL[] = R"(
436-----BEGIN X509 CRL-----
437MIIBpzCBkAIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
438CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
439Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoA4wDDAKBgNV
440HRQEAwIBATANBgkqhkiG9w0BAQwFAAOCAQEAnrBKKgvd9x9zwK9rtUvVeFeJ7+LN
441ZEAc+a5oxpPNEsJx6hXoApYEbzXMxuWBQoCs5iEBycSGudct21L+MVf27M38KrWo
442eOkq0a2siqViQZO2Fb/SUFR0k9zb8xl86Zf65lgPplALun0bV/HT7MJcl04Tc4os
443dsAReBs5nqTGNEd5AlC1iKHvQZkM//MD51DspKnDpsDiUVi54h9C1SpfZmX8H2Vv
444diyu0fZ/bPAM3VAGawatf/SyWfBMyKpoPXEG39oAzmjjOj8en82psn7m474IGaho
445/vBbhl1ms5qQiLYPjm4YELtnXQoFyC72tBjbdFd/ZE9k4CNKDbxFUXFbkw==
446-----END X509 CRL-----
447)";
448
449// kAlgorithmMismatchCRL2 is kBasicCRL but with mismatched AlgorithmIdentifiers
450// in the outer structure and signed portion. The signature reflects the outer
451// structure.
452static const char kAlgorithmMismatchCRL2[] = R"(
453-----BEGIN X509 CRL-----
454MIIBpzCBkAIBATANBgkqhkiG9w0BAQwFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
455CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
456Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoA4wDDAKBgNV
457HRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAjCWtU7AK8nQ5TCFfzvbU04MWNuLp
458iZfqapRSRyMta4pyRomK773rEmJmYOc/ZNeIphVOlupMgGC2wyv5Z/SD1mxccJbv
459SlUWciwjskjgvyyU9KnJ5xPgf3e3Fl3G0u9yJEFd4mg6fRavs5pEDX56b0f+SkG+
460Vl1FZU94Uylm2kCqk9fRpTxualPGP6dksj3Aitt4x2Vdni4sUfg9vIEEOx2jnisq
461iLqpT94IdETCWAciE0dgbogdOOsNzMqSASfHM/XPigYLXpYgfaR8fca6OKDwFsVH
462SrkFz8Se3F6mCHnbDzYElbmA46iKU2J12LTrso3Ewq/qHq0mebfp2z0y6g==
463-----END X509 CRL-----
464)";
465
David Benjamind69d94e2017-03-29 16:08:50 -0500466// kEd25519Cert is a self-signed Ed25519 certificate.
David Benjamin991835d2020-10-02 16:21:25 -0400467static const char kEd25519Cert[] = R"(
468-----BEGIN CERTIFICATE-----
469MIIBkTCCAUOgAwIBAgIJAJwooam0UCDmMAUGAytlcDBFMQswCQYDVQQGEwJBVTET
470MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
471dHkgTHRkMB4XDTE0MDQyMzIzMjE1N1oXDTE0MDUyMzIzMjE1N1owRTELMAkGA1UE
472BhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdp
473ZGdpdHMgUHR5IEx0ZDAqMAUGAytlcAMhANdamAGCsQq31Uv+08lkBzoO4XLz2qYj
474Ja8CGmj3B1Eao1AwTjAdBgNVHQ4EFgQUoux7eV+fJK2v3ah6QPU/lj1/+7UwHwYD
475VR0jBBgwFoAUoux7eV+fJK2v3ah6QPU/lj1/+7UwDAYDVR0TBAUwAwEB/zAFBgMr
476ZXADQQBuCzqji8VP9xU8mHEMjXGChX7YP5J664UyVKHKH9Z1u4wEbB8dJ3ScaWSL
477r+VHVKUhsrvcdCelnXRrrSD7xWAL
478-----END CERTIFICATE-----
479)";
David Benjamind69d94e2017-03-29 16:08:50 -0500480
481// kEd25519CertNull is an invalid self-signed Ed25519 with an explicit NULL in
482// the signature algorithm.
David Benjamin991835d2020-10-02 16:21:25 -0400483static const char kEd25519CertNull[] = R"(
484-----BEGIN CERTIFICATE-----
485MIIBlTCCAUWgAwIBAgIJAJwooam0UCDmMAcGAytlcAUAMEUxCzAJBgNVBAYTAkFV
486MRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRz
487IFB0eSBMdGQwHhcNMTQwNDIzMjMyMTU3WhcNMTQwNTIzMjMyMTU3WjBFMQswCQYD
488VQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQg
489V2lkZ2l0cyBQdHkgTHRkMCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPa
490piMlrwIaaPcHURqjUDBOMB0GA1UdDgQWBBSi7Ht5X58kra/dqHpA9T+WPX/7tTAf
491BgNVHSMEGDAWgBSi7Ht5X58kra/dqHpA9T+WPX/7tTAMBgNVHRMEBTADAQH/MAcG
492AytlcAUAA0EA70uefNocdJohkKPNROKVyBuBD3LXMyvmdTklsaxSRY3PcZdOohlr
493recgVPpVS7B+d9g4EwtZXIh4lodTBDHBBw==
494-----END CERTIFICATE-----
495)";
David Benjamind69d94e2017-03-29 16:08:50 -0500496
Adam Langley1a751ee2020-10-30 16:29:02 -0700497// kX25519 is the example X25519 certificate from
498// https://tools.ietf.org/html/rfc8410#section-10.2
499static const char kX25519Cert[] = R"(
500-----BEGIN CERTIFICATE-----
501MIIBLDCB36ADAgECAghWAUdKKo3DMDAFBgMrZXAwGTEXMBUGA1UEAwwOSUVURiBUZX
502N0IERlbW8wHhcNMTYwODAxMTIxOTI0WhcNNDAxMjMxMjM1OTU5WjAZMRcwFQYDVQQD
503DA5JRVRGIFRlc3QgRGVtbzAqMAUGAytlbgMhAIUg8AmJMKdUdIt93LQ+91oNvzoNJj
504ga9OukqY6qm05qo0UwQzAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEBAAQEAwIDCDAg
505BgNVHQ4BAQAEFgQUmx9e7e0EM4Xk97xiPFl1uQvIuzswBQYDK2VwA0EAryMB/t3J5v
506/BzKc9dNZIpDmAgs3babFOTQbs+BolzlDUwsPrdGxO3YNGhW7Ibz3OGhhlxXrCe1Cg
507w1AH9efZBw==
508-----END CERTIFICATE-----
509)";
510
Adam Langley1902d812018-03-23 11:40:45 -0700511// kSANTypesLeaf is a leaf certificate (signed by |kSANTypesRoot|) which
512// contains SANS for example.com, test@example.com, 127.0.0.1, and
513// https://example.com/. (The latter is useless for now since crypto/x509
514// doesn't deal with URI SANs directly.)
David Benjamin991835d2020-10-02 16:21:25 -0400515static const char kSANTypesLeaf[] = R"(
516-----BEGIN CERTIFICATE-----
517MIIClzCCAgCgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCsxFzAVBgNV
518BAoTDkJvcmluZ1NTTCBUZXN0MRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAw
519MDAwMFoXDTI1MDEwMTAwMDAwMFowLzEXMBUGA1UEChMOQm9yaW5nU1NMIFRlc3Qx
520FDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
521gQDbRn2TLhInBki8Bighq37EtqJd/h5SRYh6NkelCA2SQlvCgcC+l3mYQPtPbRT9
522KxOLwqUuZ9jUCZ7WIji3Sgt0cyvCNPHRk+WW2XR781ifbGE8wLBB1NkrKyQjd1sc
523O711Xc4gVM+hY4cdHiTE8x0aUIuqthRD7ZendWL0FMhS1wIDAQABo4G+MIG7MA4G
524A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYD
525VR0TAQH/BAIwADAZBgNVHQ4EEgQQn5EWH0NDPkmm3m22gNefYDAbBgNVHSMEFDAS
526gBBAN9cB+0AvuBx+VAQnjFkBMEQGA1UdEQQ9MDuCC2V4YW1wbGUuY29tgRB0ZXN0
527QGV4YW1wbGUuY29thwR/AAABhhRodHRwczovL2V4YW1wbGUuY29tLzANBgkqhkiG
5289w0BAQsFAAOBgQBtwJvY6+Tk6D6DOtDVaNoJ5y8E25CCuE/Ga4OuIcYJas+yLckf
529dZwUV3GUG2oBXl2MrpUFxXd4hKBO1CmlBY+hZEeIx0Yp6QWK9P/vnZeydOTP26mk
530jusJ2PqSmtKNU1Zcaba4d29oFejmOAfeguhR8AHpsc/zHEaS5Q9cJsuJcw==
531-----END CERTIFICATE-----
532)";
Adam Langley1902d812018-03-23 11:40:45 -0700533
534// -----BEGIN RSA PRIVATE KEY-----
535// MIICWwIBAAKBgQDbRn2TLhInBki8Bighq37EtqJd/h5SRYh6NkelCA2SQlvCgcC+
536// l3mYQPtPbRT9KxOLwqUuZ9jUCZ7WIji3Sgt0cyvCNPHRk+WW2XR781ifbGE8wLBB
537// 1NkrKyQjd1scO711Xc4gVM+hY4cdHiTE8x0aUIuqthRD7ZendWL0FMhS1wIDAQAB
538// AoGACwf7z0i1DxOI2zSwFimLghfyCSp8mgT3fbZ3Wj0SebYu6ZUffjceneM/AVrq
539// gGYHYLOVHcWJqfkl7X3hPo9SDhzLx0mM545/q21ZWCwjhswH7WiCEqV2/zeDO9WU
540// NIO1VU0VoLm0AQ7ZvwnyB+fpgF9kkkDtbBJW7XWrfNVtlnECQQD97YENpEJ3X1kj
541// 3rrkrHWDkKAyoWWY1i8Fm7LnganC9Bv6AVwgn5ZlE/479aWHF8vbOFEA3pFPiNZJ
542// t9FTCfpJAkEA3RCXjGI0Y6GALFLwEs+nL/XZAfJaIpJEZVLCVosYQOSaMS4SchfC
543// GGYVquT7ZgKk9uvz89Fg87OtBMWS9lrkHwJADGkGLKeBhBoJ3kHtem2fVK3F1pOi
544// xoR5SdnhNYVVyaxqjZ5xZTrHe+stOrr3uxGDqhQniVZXXb6/Ul0Egv1y2QJAVg/h
545// kAujba4wIhFf2VLyOZ+yjil1ocPj0LZ5Zgvcs1bMGJ1hHP3W2HzVrqRaowoggui1
546// HpTC891dXGA2qKYV7QJAFDmT2A7OVvh3y4AEgzVwHrDmCMwMHKjCIntS7fjxrJnF
547// YvJUG1zoHwUVrxxbR3DbpTODlktLcl/0b97D0IkH3w==
548// -----END RSA PRIVATE KEY-----
549
David Benjamin991835d2020-10-02 16:21:25 -0400550static const char kSANTypesRoot[] = R"(
551-----BEGIN CERTIFICATE-----
552MIICTTCCAbagAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE
553ChMOQm9yaW5nU1NMIFRlc3QxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAw
554MDAwWhcNMjUwMTAxMDAwMDAwWjArMRcwFQYDVQQKEw5Cb3JpbmdTU0wgVGVzdDEQ
555MA4GA1UEAxMHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6Q5/
556EQzmWuaGg3D2UQcuAngR9bIkkjjuJmICx5TxPqF3asCP1SJotl3iTNrghRE1wpJy
557SY2BtIiXa7f8skRb2U0GcPkMxo/ps9+jaoRsQ1m+nbLQdpvD1/qZWcO45fNTA71J
5581rPMokP+rcILuQG4VimUAySnDSghKamulFtK+Z8CAwEAAaN6MHgwDgYDVR0PAQH/
559BAQDAgIEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8E
560BTADAQH/MBkGA1UdDgQSBBBAN9cB+0AvuBx+VAQnjFkBMBsGA1UdIwQUMBKAEEA3
5611wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAc4N6hTE62/3gwg+kyc2f
562c/Jj1mHrOt+0NRaBnmvbmNpsEjHS96Ef4Wt/ZlPXPkkv1C1VosJnOIMF3Q522wRH
563bqaxARldS12VAa3gcWisDWD+SqSyDxjyojz0XDiJkTrFuCTCUiZO+1GLB7SO10Ms
564d5YVX0c90VMnUhF/dlrqS9U=
565-----END CERTIFICATE-----
566)";
Adam Langley1902d812018-03-23 11:40:45 -0700567
568// -----BEGIN RSA PRIVATE KEY-----
569// MIICXAIBAAKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1siSSOO4mYgLHlPE+oXdqwI/V
570// Imi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw+QzGj+mz36NqhGxDWb6dstB2
571// m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQDJKcNKCEpqa6UW0r5nwIDAQAB
572// AoGALEF5daZqc+aEsp8X1yky3nsoheyPL0kqSBWii33IFemZgKcSaRnAoqjPWWLS
573// 8dHj0I/4rej2MW8iuezVSpDak9tK5boHORC3w4p/wifkizQkLt1DANxTVbzcKvrt
574// aZ7LjVaKkhjRJbLddniowFHkkWVbUccjvzcUd7Y2VuLbAhECQQDq4FE88aHio8zg
575// bxSd0PwjEFwLYQTR19u812SoR8PmR6ofIL+pDwOV+fVs+OGcAAOgkhIukOrksQ4A
576// 1cKtnyhXAkEA/gRI+u3tZ7UE1twIkBfZ6IvCdRodkPqHAYIxMRLzL+MhyZt4MEGc
577// Ngb/F6U9/WOBFnoR/PI7IwE3ejutzKcL+QJBAKh+6eilk7QKPETZi1m3/dmNt+p1
578// 3EZJ65pqjwxmB3Rg/vs7vCMk4TarTdSyKu+F1xRPFfoP/mK3Xctdjj6NyhsCQAYF
579// 7/0TOzfkUPMPUJyqFB6xgbDpJ55ScnUUsznoqx+NkTWInDb4t02IqO/UmT2y6FKy
580// Hk8TJ1fTJY+ebqaVp3ECQApx9gQ+n0zIhx97FMUuiRse73xkcW4+pZ8nF+8DmeQL
581// /JKuuFGmzkG+rUbXFmo/Zg2ozVplw71NnQJ4znPsf7A=
582// -----END RSA PRIVATE KEY-----
583
Adam Langley0224a322018-07-31 16:19:17 -0700584// The following four certificates were generated with this Go program, varying
585// |includeNetscapeExtension| and defining rootKeyPEM and rootCertPEM to be
586// strings containing the kSANTypesRoot, above.
587
588// package main
589
590// import (
591// "crypto/ecdsa"
592// "crypto/elliptic"
593// "crypto/rand"
594// "crypto/x509"
595// "crypto/x509/pkix"
596// "encoding/asn1"
597// "encoding/pem"
598// "math/big"
599// "os"
600// "time"
601// )
602
603// const includeNetscapeExtension = true
604
605// func main() {
606// block, _ := pem.Decode([]byte(rootKeyPEM))
607// rootPriv, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
608// block, _ = pem.Decode([]byte(rootCertPEM))
609// root, _ := x509.ParseCertificate(block.Bytes)
610
611// interTemplate := &x509.Certificate{
612// SerialNumber: big.NewInt(2),
613// Subject: pkix.Name{
614// CommonName: "No Basic Constraints (Netscape)",
615// },
616// NotBefore: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
617// NotAfter: time.Date(2099, time.January, 1, 0, 0, 0, 0, time.UTC),
618// }
619
620// if includeNetscapeExtension {
621// interTemplate.ExtraExtensions = []pkix.Extension{
622// pkix.Extension{
623// Id: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 113730, 1, 1}),
624// Value: []byte{0x03, 0x02, 2, 0x04},
625// },
626// }
627// } else {
628// interTemplate.KeyUsage = x509.KeyUsageCertSign
629// }
630
631// interKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
632
633// interDER, err := x509.CreateCertificate(rand.Reader, interTemplate, root, &interKey.PublicKey, rootPriv)
634// if err != nil {
635// panic(err)
636// }
637
638// pem.Encode(os.Stdout, &pem.Block{Type: "CERTIFICATE", Bytes: interDER})
639
640// inter, _ := x509.ParseCertificate(interDER)
641
642// leafTemplate := &x509.Certificate{
643// SerialNumber: big.NewInt(3),
644// Subject: pkix.Name{
645// CommonName: "Leaf from CA with no Basic Constraints",
646// },
647// NotBefore: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
648// NotAfter: time.Date(2099, time.January, 1, 0, 0, 0, 0, time.UTC),
649// BasicConstraintsValid: true,
650// }
651// leafKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
652
653// leafDER, err := x509.CreateCertificate(rand.Reader, leafTemplate, inter, &leafKey.PublicKey, interKey)
654// if err != nil {
655// panic(err)
656// }
657
658// pem.Encode(os.Stdout, &pem.Block{Type: "CERTIFICATE", Bytes: leafDER})
659// }
660
661// kNoBasicConstraintsCertSignIntermediate doesn't have isCA set, but contains
662// certSign in the keyUsage.
David Benjamin991835d2020-10-02 16:21:25 -0400663static const char kNoBasicConstraintsCertSignIntermediate[] = R"(
664-----BEGIN CERTIFICATE-----
665MIIBqjCCAROgAwIBAgIBAjANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
666bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
667MDk5MDEwMTAwMDAwMFowHzEdMBsGA1UEAxMUTm8gQmFzaWMgQ29uc3RyYWludHMw
668WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASEFMblfxIEDO8My7wHtHWTuDzNyID1
669OsPkMGkn32O/pSyXxXuAqDeFoMVffUMTyfm8JcYugSEbrv2qEXXM4bZRoy8wLTAO
670BgNVHQ8BAf8EBAMCAgQwGwYDVR0jBBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkq
671hkiG9w0BAQsFAAOBgQC1Lh6hIAm3K5kRh5iIydU0YAEm7eV6ZSskERDUq3DLJyl9
672ZUZCHUzvb464dkwZjeNzaUVS1pdElJslwX3DtGgeJLJGCnk8zUjBjaNrrDm0kzPW
673xKt/6oif1ci/KCKqKNXJAIFbc4e+IiBpenwpxHk3If4NM+Ek0nKoO8Uj0NkgTQ==
674-----END CERTIFICATE-----
675)";
Adam Langley0224a322018-07-31 16:19:17 -0700676
David Benjamin991835d2020-10-02 16:21:25 -0400677static const char kNoBasicConstraintsCertSignLeaf[] = R"(
678-----BEGIN CERTIFICATE-----
679MIIBUDCB96ADAgECAgEDMAoGCCqGSM49BAMCMB8xHTAbBgNVBAMTFE5vIEJhc2lj
680IENvbnN0cmFpbnRzMCAXDTAwMDEwMTAwMDAwMFoYDzIwOTkwMTAxMDAwMDAwWjAx
681MS8wLQYDVQQDEyZMZWFmIGZyb20gQ0Egd2l0aCBubyBCYXNpYyBDb25zdHJhaW50
682czBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEsYPMwzdJKjB+2gpC90ib2ilHoB
683w/arQ6ikUX0CNUDDaKaOu/jF39ogzVlg4lDFrjCKShSfCCcrwgONv70IZGijEDAO
684MAwGA1UdEwEB/wQCMAAwCgYIKoZIzj0EAwIDSAAwRQIgbV7R99yM+okXSIs6Fp3o
685eCOXiDL60IBxaTOcLS44ywcCIQDbn87Gj5cFgHBYAkzdHqDsyGXkxQTHDq9jmX24
686Djy3Zw==
687-----END CERTIFICATE-----
688)";
Adam Langley0224a322018-07-31 16:19:17 -0700689
690// kNoBasicConstraintsNetscapeCAIntermediate doesn't have isCA set, but contains
691// a Netscape certificate-type extension that asserts a type of "SSL CA".
David Benjamin991835d2020-10-02 16:21:25 -0400692static const char kNoBasicConstraintsNetscapeCAIntermediate[] = R"(
693-----BEGIN CERTIFICATE-----
694MIIBuDCCASGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
695bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
696MDk5MDEwMTAwMDAwMFowKjEoMCYGA1UEAxMfTm8gQmFzaWMgQ29uc3RyYWludHMg
697KE5ldHNjYXBlKTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCeMbmCaOtMzXBqi
698PrCdNOH23CkaawUA+pAezitAN4RXS1O2CGK5sJjGPVVeogROU8G7/b+mU+ciZIzH
6991PP8FJKjMjAwMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5UBCeMWQEwEQYJYIZIAYb4
700QgEBBAQDAgIEMA0GCSqGSIb3DQEBCwUAA4GBAAgNWjh7cfBTClTAk+Ml//5xb9Ju
701tkBhG6Rm+kkMD+qiSMO6t7xS7CsA0+jIBjkdEYaLZ3oxtQCBdZsVNxUvRxZ0AUfF
702G3DtRFTsrI1f7IQhpMuqEMF4shPW+5x54hrq0Fo6xMs6XoinJZcTUaaB8EeXRF6M
703P9p6HuyLrmn0c/F0
704-----END CERTIFICATE-----
705)";
Adam Langley0224a322018-07-31 16:19:17 -0700706
David Benjamin991835d2020-10-02 16:21:25 -0400707static const char kNoBasicConstraintsNetscapeCALeaf[] = R"(
708-----BEGIN CERTIFICATE-----
709MIIBXDCCAQKgAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9ObyBCYXNp
710YyBDb25zdHJhaW50cyAoTmV0c2NhcGUpMCAXDTAwMDEwMTAwMDAwMFoYDzIwOTkw
711MTAxMDAwMDAwWjAxMS8wLQYDVQQDEyZMZWFmIGZyb20gQ0Egd2l0aCBubyBCYXNp
712YyBDb25zdHJhaW50czBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDlJKolDu3R2
713tPqSDycr0QJcWhxdBv76V0EEVflcHRxED6vAioTEcnQszt1OfKtBZvjlo0yp6i6Q
714DaYit0ZInmWjEDAOMAwGA1UdEwEB/wQCMAAwCgYIKoZIzj0EAwIDSAAwRQIhAJsh
715aZL6BHeEfoUBj1oZ2Ln91qzj3UCVMJ+vrmwAFdYyAiA3wp2JphgchvmoUFuzPXwj
716XyPwWPbymSTpzKhB4xB7qQ==
717-----END CERTIFICATE-----
718)";
Adam Langley1902d812018-03-23 11:40:45 -0700719
David Benjamin991835d2020-10-02 16:21:25 -0400720static const char kSelfSignedMismatchAlgorithms[] = R"(
721-----BEGIN CERTIFICATE-----
722MIIFMjCCAxqgAwIBAgIJAL0mG5fOeJ7xMA0GCSqGSIb3DQEBDQUAMC0xCzAJBgNV
723BAYTAkdCMQ8wDQYDVQQHDAZMb25kb24xDTALBgNVBAoMBFRlc3QwIBcNMTgwOTE3
724MTIxNzU3WhgPMjExODA4MjQxMjE3NTdaMC0xCzAJBgNVBAYTAkdCMQ8wDQYDVQQH
725DAZMb25kb24xDTALBgNVBAoMBFRlc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
726ggIKAoICAQDCMhBrRAGGw+n2GdctBr/cEK4FZA6ajiHjihgpCHoSBdyL4R2jGKLS
727g0WgaMXa1HpkKN7LcIySosEBPlmcRkr1RqbEvQStOSvoFCXYvtx3alM6HTbXMcDR
728mqoKoABP6LXsPSoMWIgqMtP2X9EOppzHVIK1yFYFfbIlvYUV2Ka+MuMe0Vh5wvD1
7294GanPb+cWSKgdRSVQovCCMY3yWtZKVEaxRpCsk/mYYIFWz0tcgMjIKwDx1XXgiAV
730nU6NK43xbaw3XhtnaD/pv9lhTTbNrlcln9LjTD097BaK4R+1AEPHnpfxA9Ui3upn
731kbsNUdGdOB0ksZi/vd7lh833YgquQUIAhYrbfvq/HFCpVV1gljzlS3sqULYpLE//
732i3OsuL2mE+CYIJGpIi2GeJJWXciNMTJDOqTn+fRDtVb4RPp4Y70DJirp7XzaBi3q
733H0edANCzPSRCDbZsOhzIXhXshldiXVRX666DDlbMQgLTEnNKrkwv6DmU8o15XQsb
7348k1Os2YwXmkEOxUQ7AJZXVTZSf6UK9Znmdq1ZrHjybMfRUkHVxJcnKvrxfryralv
735gzfvu+D6HuxrCo3Ojqa+nDgIbxKEBtdrcsMhq1jWPFhjwo1fSadAkKOfdCAuXJRD
736THg3b4Sf+W7Cpc570YHrIpBf7WFl2XsPcEM0mJZ5+yATASCubNozQwIDAQABo1Mw
737UTAdBgNVHQ4EFgQUES0hupZSqY21JOba10QyZuxm91EwHwYDVR0jBBgwFoAUES0h
738upZSqY21JOba10QyZuxm91EwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF
739AAOCAgEABTN5S30ng/RMpBweDm2N561PdpaCdiRXtAFCRVWR2mkDYC/Xj9Vqe6be
740PyM7L/5OKYVjzF1yJu67z/dx+ja5o+41g17jdqla7hyPx+9B4uRyDh+1KJTa+duj
741mw/aA1LCr6O6W4WizDOsChJ6FaB2Y1+GlFnKWb5nUdhVJqXQE1WOX9dZnw8Y4Npd
742VmAsjWot0BZorJrt3fwfcv3QfA896twkbo7Llv/8qzg4sXZXZ4ZtgAOqnPngiSn+
743JT/vYCXZ406VvAFpFqMcVz2dO/VGuL8lGIMHRKNyafrsV81EzH1W/XmRWOgvgj6r
744yQI63ln/AMY72HQ97xLkE1xKunGz6bK5Ug5+O43Uftc4Mb6MUgzo+ZqEQ3Ob+cAV
745cvjmtwDaPO/O39O5Xq0tLTlkn2/cKf4OQ6S++GDxzyRVHh5JXgP4j9+jfZY57Woy
746R1bE7N50JjY4cDermBJKdlBIjL7UPhqmLyaG7V0hBitFlgGBUCcJtJOV0xYd5aF3
747pxNkvMXhBmh95fjxJ0cJjpO7tN1RAwtMMNgsl7OUbuVRQCHOPW5DgP5qY21jDeRn
748BY82382l+9QzykmJLI5MZnmj4BA9uIDCwMtoTTvP++SsvhUAbuvh7MOOUQL0EY4m
749KStYq7X9PKseN+PvmfeoffIKc5R/Ha39oi7cGMVHCr8aiEhsf94=
750-----END CERTIFICATE-----
751)";
David Benjamin371305f2018-09-18 13:14:53 -0700752
David Benjaminc60b42b2019-04-16 13:57:11 -0500753// kCommonNameWithSANs is a leaf certificate signed by kSANTypesRoot, with
754// *.host1.test as the common name and a SAN list of *.host2.test and
755// foo.host3.test.
David Benjamin991835d2020-10-02 16:21:25 -0400756static const char kCommonNameWithSANs[] = R"(
757-----BEGIN CERTIFICATE-----
758MIIB2zCCAUSgAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
759bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
760MDk5MDEwMTAwMDAwMFowNzEeMBwGA1UEChMVQ29tbW9uIG5hbWUgd2l0aCBTQU5z
761MRUwEwYDVQQDDAwqLmhvc3QxLnRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
762AASgWzfnFnpQrokSLIC+LhCKJDUAY/2usfIDpOnafYoYCasbYetkmOslgyY4Nn07
763zjvjNROprA/0bdULXAkdL9bNo0gwRjAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQn
764jFkBMCcGA1UdEQQgMB6CDCouaG9zdDIudGVzdIIOZm9vLmhvc3QzLnRlc3QwDQYJ
765KoZIhvcNAQELBQADgYEAtv2e3hBhsslXB1HTxgusjoschWOVtvGZUaYlhkKzKTCL
7664YpDn50BccnucBU/b9phYvaEZtyzOv4ZXhxTGyLnLrIVB9x5ikfCcfl+LNYNjDwM
767enm/h1zOfJ7wXLyscD4kU29Wc/zxBd70thIgLYn16CC1S9NtXKsXXDXv5VVH/bg=
768-----END CERTIFICATE-----
769)";
David Benjaminc60b42b2019-04-16 13:57:11 -0500770
771// kCommonNameWithSANs is a leaf certificate signed by kSANTypesRoot, with
772// *.host1.test as the common name and no SAN list.
David Benjamin991835d2020-10-02 16:21:25 -0400773static const char kCommonNameWithoutSANs[] = R"(
774-----BEGIN CERTIFICATE-----
775MIIBtTCCAR6gAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
776bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
777MDk5MDEwMTAwMDAwMFowOjEhMB8GA1UEChMYQ29tbW9uIG5hbWUgd2l0aG91dCBT
778QU5zMRUwEwYDVQQDDAwqLmhvc3QxLnRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMB
779BwNCAARt2vjlIrPE+kr11VS1rRP/AYQu4fvf1bNw/K9rwYlVBhmLMPYasEmpCtKE
7800bDIFydtDYC3wZDpSS+YiaG40sdAox8wHTAbBgNVHSMEFDASgBBAN9cB+0AvuBx+
781VAQnjFkBMA0GCSqGSIb3DQEBCwUAA4GBAHRbIeaCEytOpJpw9O2dlB656AHe1+t5
7824JiS5mvtzoVOLn7fFk5EFQtZS7sG1Uc2XjlSw+iyvFoTFEqfKyU/mIdc2vBuPwA2
783+YXT8aE4S+UZ9oz5j0gDpikGnkSCW0cyHD8L8fntNjaQRSaM482JpmtdmuxClmWO
784pFFXI2B5usgI
785-----END CERTIFICATE-----
786)";
David Benjaminc60b42b2019-04-16 13:57:11 -0500787
David Benjamind86eb1b2019-04-17 17:38:52 -0500788// kCommonNameWithEmailSAN is a leaf certificate signed by kSANTypesRoot, with
789// *.host1.test as the common name and the email address test@host2.test in the
790// SAN list.
David Benjamin991835d2020-10-02 16:21:25 -0400791static const char kCommonNameWithEmailSAN[] = R"(
792-----BEGIN CERTIFICATE-----
793MIIBvDCCASWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
794bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
795MDk5MDEwMTAwMDAwMFowFzEVMBMGA1UEAwwMKi5ob3N0MS50ZXN0MFkwEwYHKoZI
796zj0CAQYIKoZIzj0DAQcDQgAEtevOxcTjpPzlNGoUMFfZyr1k03/Hiuh+EsnuScDs
7978XLKi6fDkvSaDClI99ycabQZRPIrvyT+dglDC6ugQd+CYqNJMEcwDAYDVR0TAQH/
798BAIwADAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMBoGA1UdEQQTMBGBD3Rl
799c3RAaG9zdDIudGVzdDANBgkqhkiG9w0BAQsFAAOBgQCGbqb78OWJWl4zb+qw0Dz2
800HJgZZJt6/+nNG/XJKdaYeS4eofsbwsJI4fuuOF6ZvYCJxVNtGqdfZDgycvFA9hjv
801NGosBF1/spP17cmzTahLjxs71jDvHV/EQJbKGl/Zpta1Em1VrzSrwoOFabPXzZTJ
802aet/mER21Z/9ZsTUoJQPJw==
803-----END CERTIFICATE-----
804)";
David Benjamind86eb1b2019-04-17 17:38:52 -0500805
806// kCommonNameWithIPSAN is a leaf certificate signed by kSANTypesRoot, with
807// *.host1.test as the common name and the IP address 127.0.0.1 in the
808// SAN list.
David Benjamin991835d2020-10-02 16:21:25 -0400809static const char kCommonNameWithIPSAN[] = R"(
810-----BEGIN CERTIFICATE-----
811MIIBsTCCARqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
812bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
813MDk5MDEwMTAwMDAwMFowFzEVMBMGA1UEAwwMKi5ob3N0MS50ZXN0MFkwEwYHKoZI
814zj0CAQYIKoZIzj0DAQcDQgAEFKrgkxm8PysXbwnHQeTD3p8YY0+sY4ssnZgmj8wX
815KTyn893fdBHWlz71GO6t82wMTF5d+ZYwI2XU52pfl4SB2aM+MDwwDAYDVR0TAQH/
816BAIwADAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMA8GA1UdEQQIMAaHBH8A
817AAEwDQYJKoZIhvcNAQELBQADgYEAQWZ8Oj059ZjS109V/ijMYT28xuAN5n6HHxCO
818DopTP56Zu9+gme5wTETWEfocspZvgecoUOcedTFoKSQ7JafO09NcVLA+D6ddYpju
819mgfuiLy9dDhqvX/NHaLBMxOBWWbOLwWE+ibyX+pOzjWRCw1L7eUXOr6PhZAOQsmU
820D0+O6KI=
821-----END CERTIFICATE-----
822)";
David Benjamind86eb1b2019-04-17 17:38:52 -0500823
David Benjaminc67076d2019-04-16 17:39:50 -0500824// kConstrainedIntermediate is an intermediate signed by kSANTypesRoot, with
825// permitted DNS names of permitted1.test and foo.permitted2.test and an
826// excluded DNS name of excluded.permitted1.test. Its private key is:
827//
828// -----BEGIN PRIVATE KEY-----
829// MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTXUM4tJWM7OzATty
830// JhNOfIv/d8heWFBeKOfMR+RfaROhRANCAASbbbWYiN6mn+BCpg4XNpibOH0D/DN4
831// kZ5C/Ml2YVomC9T83OKk2CzB8fPAabPb4P4Vv+fIabpEfjWS5nzKLY1y
832// -----END PRIVATE KEY-----
David Benjamin991835d2020-10-02 16:21:25 -0400833static const char kConstrainedIntermediate[] = R"(
834-----BEGIN CERTIFICATE-----
835MIICDjCCAXegAwIBAgIBAjANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
836bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
837MDk5MDEwMTAwMDAwMFowKDEmMCQGA1UEAxMdTmFtZSBDb25zdHJhaW50cyBJbnRl
838cm1lZGlhdGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASbbbWYiN6mn+BCpg4X
839NpibOH0D/DN4kZ5C/Ml2YVomC9T83OKk2CzB8fPAabPb4P4Vv+fIabpEfjWS5nzK
840LY1yo4GJMIGGMA8GA1UdEwEB/wQFMAMBAf8wGwYDVR0jBBQwEoAQQDfXAftAL7gc
841flQEJ4xZATBWBgNVHR4BAf8ETDBKoCowEYIPcGVybWl0dGVkMS50ZXN0MBWCE2Zv
842by5wZXJtaXR0ZWQyLnRlc3ShHDAaghhleGNsdWRlZC5wZXJtaXR0ZWQxLnRlc3Qw
843DQYJKoZIhvcNAQELBQADgYEAFq1Ka05hiKREwRpSceQPzIIH4B5a5IVBg5/EvmQI
8449V0fXyAE1GmahPt70sIBxIgzNTEaY8P/IoOuCdlZWe0msmyEO3S6YSAzOWR5Van6
845cXmFM1uMd95TlkxUMRdV+jKJTvG6R/BM2zltaV7Xt662k5HtzT5Svw0rZlFaggZz
846UyM=
847-----END CERTIFICATE-----
848)";
David Benjaminc67076d2019-04-16 17:39:50 -0500849
850// kCommonNamePermittedLeaf is a leaf certificate signed by
851// kConstrainedIntermediate. Its common name is permitted by the name
852// constraints.
David Benjamin991835d2020-10-02 16:21:25 -0400853static const char kCommonNamePermittedLeaf[] = R"(
854-----BEGIN CERTIFICATE-----
855MIIBaDCCAQ2gAwIBAgIBAzAKBggqhkjOPQQDAjAoMSYwJAYDVQQDEx1OYW1lIENv
856bnN0cmFpbnRzIEludGVybWVkaWF0ZTAgFw0wMDAxMDEwMDAwMDBaGA8yMDk5MDEw
857MTAwMDAwMFowPjEeMBwGA1UEChMVQ29tbW9uIG5hbWUgcGVybWl0dGVkMRwwGgYD
858VQQDExNmb28ucGVybWl0dGVkMS50ZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
859QgAENX5Ycs8q8MRzPYUz6DqLHhJR3wcmniFRgkiEa7MxE/mRe00y0VGwH7xi7Aoc
860emXPrtD4JwN5bssbcxWGAKYYzaMQMA4wDAYDVR0TAQH/BAIwADAKBggqhkjOPQQD
861AgNJADBGAiEAtsnWuRQXtw2xbieC78Y8SVEtTjcZUx8uZyQe1GPLfGICIQDR4fNY
862yg3PC94ydPNQZVsFxAne32CbonWWsokalTFpUQ==
863-----END CERTIFICATE-----
864)";
David Benjaminc67076d2019-04-16 17:39:50 -0500865static const char kCommonNamePermitted[] = "foo.permitted1.test";
866
867// kCommonNameNotPermittedLeaf is a leaf certificate signed by
868// kConstrainedIntermediate. Its common name is not permitted by the name
869// constraints.
David Benjamin991835d2020-10-02 16:21:25 -0400870static const char kCommonNameNotPermittedLeaf[] = R"(
871-----BEGIN CERTIFICATE-----
872MIIBazCCARCgAwIBAgIBBDAKBggqhkjOPQQDAjAoMSYwJAYDVQQDEx1OYW1lIENv
873bnN0cmFpbnRzIEludGVybWVkaWF0ZTAgFw0wMDAxMDEwMDAwMDBaGA8yMDk5MDEw
874MTAwMDAwMFowQTEiMCAGA1UEChMZQ29tbW9uIG5hbWUgbm90IHBlcm1pdHRlZDEb
875MBkGA1UEAxMSbm90LXBlcm1pdHRlZC50ZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D
876AQcDQgAEzfghKuWf0JoXb0Drp09C3yXMSQQ1byt+AUaymvsHOWsxQ9v1Q+vkF/IM
877HRqGTk2TyxrB2iClVEn/Uu+YtYox1KMQMA4wDAYDVR0TAQH/BAIwADAKBggqhkjO
878PQQDAgNJADBGAiEAxaUslxmoWL1tIvnDz7gDkto/HcmdU0jHVuUQLXcCG8wCIQCN
8795xZjitlCQU8UB5qSu9wH4B+0JcVO3Ss4Az76HEJWMw==
880-----END CERTIFICATE-----
881)";
David Benjaminc67076d2019-04-16 17:39:50 -0500882static const char kCommonNameNotPermitted[] = "not-permitted.test";
883
884// kCommonNameNotPermittedWithSANsLeaf is a leaf certificate signed by
885// kConstrainedIntermediate. Its common name is not permitted by the name
886// constraints but it has a SAN list.
David Benjamin991835d2020-10-02 16:21:25 -0400887static const char kCommonNameNotPermittedWithSANsLeaf[] = R"(
888-----BEGIN CERTIFICATE-----
889MIIBqTCCAU+gAwIBAgIBBjAKBggqhkjOPQQDAjAoMSYwJAYDVQQDEx1OYW1lIENv
890bnN0cmFpbnRzIEludGVybWVkaWF0ZTAgFw0wMDAxMDEwMDAwMDBaGA8yMDk5MDEw
891MTAwMDAwMFowSzEsMCoGA1UEChMjQ29tbW9uIG5hbWUgbm90IHBlcm1pdHRlZCB3
892aXRoIFNBTlMxGzAZBgNVBAMTEm5vdC1wZXJtaXR0ZWQudGVzdDBZMBMGByqGSM49
893AgEGCCqGSM49AwEHA0IABKsn9wOApXFHrqhLdQgbFSeaSoAIbxgO0zVSRZUb5naR
89493zoL3MFOvZEF8xiEqh7le+l3XuUig0fwqpcsZzRNJajRTBDMAwGA1UdEwEB/wQC
895MAAwMwYDVR0RBCwwKoITZm9vLnBlcm1pdHRlZDEudGVzdIITZm9vLnBlcm1pdHRl
896ZDIudGVzdDAKBggqhkjOPQQDAgNIADBFAiACk+1f184KkKAXuntmrz+Ygcq8MiZl
8974delx44FtcNaegIhAIA5nYfzxNcTXxDo3U+x1vSLH6Y7faLvHiFySp7O//q+
898-----END CERTIFICATE-----
899)";
David Benjaminc67076d2019-04-16 17:39:50 -0500900static const char kCommonNameNotPermittedWithSANs[] = "not-permitted.test";
901
902// kCommonNameNotDNSLeaf is a leaf certificate signed by
903// kConstrainedIntermediate. Its common name is not a DNS name.
David Benjamin991835d2020-10-02 16:21:25 -0400904static const char kCommonNameNotDNSLeaf[] = R"(
905-----BEGIN CERTIFICATE-----
906MIIBYTCCAQagAwIBAgIBCDAKBggqhkjOPQQDAjAoMSYwJAYDVQQDEx1OYW1lIENv
907bnN0cmFpbnRzIEludGVybWVkaWF0ZTAgFw0wMDAxMDEwMDAwMDBaGA8yMDk5MDEw
908MTAwMDAwMFowNzEcMBoGA1UEChMTQ29tbW9uIG5hbWUgbm90IEROUzEXMBUGA1UE
909AxMOTm90IGEgRE5TIG5hbWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASnueyc
910Zxtnw5ke2J2T0/LwAK37auQP/RSFd9mem+BJVbgviawtAlignJmafp7Zw4/GdYEJ
911Vm8qlriOJtluvXGcoxAwDjAMBgNVHRMBAf8EAjAAMAoGCCqGSM49BAMCA0kAMEYC
912IQChUAmVNI39VHe0zemRE09VDcSEgOxr1nTvjLcg/Q8pVQIhAJYZnJI0YZAi05QH
913RHNlAkTK2TnUaVn3fGSylaLiFS1r
914-----END CERTIFICATE-----
915)";
David Benjaminc67076d2019-04-16 17:39:50 -0500916static const char kCommonNameNotDNS[] = "Not a DNS name";
917
Adam Langleybb507832019-09-17 12:56:01 -0700918// The following six certificates are issued by |kSANTypesRoot| and have
919// different extended key usage values. They were created with the following
920// Go program:
921//
922// func main() {
923// block, _ := pem.Decode([]byte(rootKeyPEM))
924// rootPriv, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
925// block, _ = pem.Decode([]byte(rootCertPEM))
926// root, _ := x509.ParseCertificate(block.Bytes)
927//
928// leafTemplate := &x509.Certificate{
929// SerialNumber: big.NewInt(3),
930// Subject: pkix.Name{
931// CommonName: "EKU msSGC",
932// },
933// NotBefore: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
934// NotAfter: time.Date(2099, time.January, 1, 0, 0, 0, 0, time.UTC),
935// BasicConstraintsValid: true,
936// ExtKeyUsage: []x509.ExtKeyUsage{FILL IN HERE},
937// }
938// leafKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
939// leafDER, err := x509.CreateCertificate(rand.Reader, leafTemplate, root, &leafKey.PublicKey, rootPriv)
940// if err != nil {
941// panic(err)
942// }
943// pem.Encode(os.Stdout, &pem.Block{Type: "CERTIFICATE", Bytes: leafDER})
944// }
945
David Benjamin991835d2020-10-02 16:21:25 -0400946static const char kMicrosoftSGCCert[] = R"(
947-----BEGIN CERTIFICATE-----
948MIIBtDCCAR2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
949bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
950MDk5MDEwMTAwMDAwMFowFDESMBAGA1UEAxMJRUtVIG1zU0dDMFkwEwYHKoZIzj0C
951AQYIKoZIzj0DAQcDQgAEEn61v3Vs+q6bTyyRnrJvuKBE8PTNVLbXGB52jig4Qse2
952mGygNEysS0uzZ0luz+rn2hDRUFL6sHLUs1d8UMbI/6NEMEIwFQYDVR0lBA4wDAYK
953KwYBBAGCNwoDAzAMBgNVHRMBAf8EAjAAMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5U
954BCeMWQEwDQYJKoZIhvcNAQELBQADgYEAgDQI9RSo3E3ZVnU71TV/LjG9xwHtfk6I
955rlNnlJJ0lsTHAuMc1mwCbzhtsmasetwYlIa9G8GFWB9Gh/QqHA7G649iGGmXShqe
956aVDuWgeSEJxBPE2jILoMm4pEYF7jfonTn7XXX6O78yuSlP+NPIU0gUKHkWZ1sWk0
957cC4l0r/6jik=
958-----END CERTIFICATE-----
959)";
Adam Langleybb507832019-09-17 12:56:01 -0700960
David Benjamin991835d2020-10-02 16:21:25 -0400961static const char kNetscapeSGCCert[] = R"(
962-----BEGIN CERTIFICATE-----
963MIIBszCCARygAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
964bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
965MDk5MDEwMTAwMDAwMFowFDESMBAGA1UEAxMJRUtVIG1zU0dDMFkwEwYHKoZIzj0C
966AQYIKoZIzj0DAQcDQgAE3NbT+TnBfq1DWJCezjaUL52YhDU7cOkI2S2PoWgJ1v7x
967kKLwBonUFZjppZs69SyBHeJdti+KoJ3qTW+hCG08EaNDMEEwFAYDVR0lBA0wCwYJ
968YIZIAYb4QgQBMAwGA1UdEwEB/wQCMAAwGwYDVR0jBBQwEoAQQDfXAftAL7gcflQE
969J4xZATANBgkqhkiG9w0BAQsFAAOBgQBuiyVcfazekHkCWksxdFmjPmMtWCxFjkzc
9708VBxFE0CfSHQAfZ8J7tXd1FbAq/eXdZvvo8v0JB4sOM4Ex1ob1fuvDFHdSAHAD7W
971dhKIjJyzVojoxjCjyue0XMeEPl7RiqbdxoS/R5HFAqAF0T2OeQAqP9gTpOXoau1M
972RQHX6HQJJg==
973-----END CERTIFICATE-----
974)";
Adam Langleybb507832019-09-17 12:56:01 -0700975
David Benjamin991835d2020-10-02 16:21:25 -0400976static const char kServerEKUCert[] = R"(
977-----BEGIN CERTIFICATE-----
978MIIBsjCCARugAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
979bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
980MDk5MDEwMTAwMDAwMFowFDESMBAGA1UEAxMJRUtVIG1zU0dDMFkwEwYHKoZIzj0C
981AQYIKoZIzj0DAQcDQgAEDd35i+VWPwIOKLrLWTuP5cqD+yJDB5nujEzPgkXP5LKJ
982SZRbHTqTdpYZB2jy6y90RY2Bsjx7FfZ7nN5G2g1GOKNCMEAwEwYDVR0lBAwwCgYI
983KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQn
984jFkBMA0GCSqGSIb3DQEBCwUAA4GBAIKmbMBjuivL/rxDu7u7Vr3o3cdmEggBJxwL
985iatNW3x1wg0645aNYOktW/iQ7mAAiziTY73GFyfiJDWqnY+CwA94ZWyQidjHdN/I
9866BR52sN/dkYEoInYEbmDNMc/if+T0yqeBQLP4BeKLiT8p0qqaimae6LgibS19hDP
9872hoEMdz2
988-----END CERTIFICATE-----
989)";
Adam Langleybb507832019-09-17 12:56:01 -0700990
David Benjamin991835d2020-10-02 16:21:25 -0400991static const char kServerEKUPlusMicrosoftSGCCert[] = R"(
992-----BEGIN CERTIFICATE-----
993MIIBvjCCASegAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
994bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
995MDk5MDEwMTAwMDAwMFowFDESMBAGA1UEAxMJRUtVIG1zU0dDMFkwEwYHKoZIzj0C
996AQYIKoZIzj0DAQcDQgAEDO1MYPxq+U4oXMIK8UnsS4C696wpcu4UOmcMJJ5CUd5Z
997ZpJShN6kYKnrb3GK/6xEgbUGntmrzSRG5FYqk6QgD6NOMEwwHwYDVR0lBBgwFgYI
998KwYBBQUHAwEGCisGAQQBgjcKAwMwDAYDVR0TAQH/BAIwADAbBgNVHSMEFDASgBBA
999N9cB+0AvuBx+VAQnjFkBMA0GCSqGSIb3DQEBCwUAA4GBAHOu2IBa4lHzVGS36HxS
1000SejUE87Ji1ysM6BgkYbfxfS9MuV+J3UnqH57JjbH/3CFl4ZDWceF6SGBSCn8LqKa
1001KHpwoNFU3zA99iQzVJgbUyN0PbKwHEanLyKDJZyFk71R39ToxhSNQgaQYjZYCy1H
10025V9oXd1bodEqVsOZ/mur24Ku
1003-----END CERTIFICATE-----
1004)";
Adam Langleybb507832019-09-17 12:56:01 -07001005
David Benjamin991835d2020-10-02 16:21:25 -04001006static const char kAnyEKU[] = R"(
1007-----BEGIN CERTIFICATE-----
1008MIIBrjCCARegAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
1009bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
1010MDk5MDEwMTAwMDAwMFowFDESMBAGA1UEAxMJRUtVIG1zU0dDMFkwEwYHKoZIzj0C
1011AQYIKoZIzj0DAQcDQgAE9nsLABDporlTvx1OBUc4Hd5vxfX+8nS/OhbHmKtFLYNu
10121CLLrImbwMQYD2G+PgLO6sQHmASq2jmJKp6ZWsRkTqM+MDwwDwYDVR0lBAgwBgYE
1013VR0lADAMBgNVHRMBAf8EAjAAMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5UBCeMWQEw
1014DQYJKoZIhvcNAQELBQADgYEAxgjgn1SAzQ+2GeCicZ5ndvVhKIeFelGCQ989XTVq
1015uUbAYBW6v8GXNuVzoXYxDgNSanF6U+w+INrJ6daKVrIxAxdk9QFgBXqJoupuRAA3
1016/OqnmYux0EqOTLbTK1P8DhaiaD0KV6dWGUwzqsgBmPkZ0lgNaPjvb1mKV3jhBkjz
1017L6A=
1018-----END CERTIFICATE-----
1019)";
Adam Langleybb507832019-09-17 12:56:01 -07001020
David Benjamin991835d2020-10-02 16:21:25 -04001021static const char kNoEKU[] = R"(
1022-----BEGIN CERTIFICATE-----
1023MIIBnTCCAQagAwIBAgIBAzANBgkqhkiG9w0BAQsFADArMRcwFQYDVQQKEw5Cb3Jp
1024bmdTU0wgVGVzdDEQMA4GA1UEAxMHUm9vdCBDQTAgFw0wMDAxMDEwMDAwMDBaGA8y
1025MDk5MDEwMTAwMDAwMFowFDESMBAGA1UEAxMJRUtVIG1zU0dDMFkwEwYHKoZIzj0C
1026AQYIKoZIzj0DAQcDQgAEpSFSqbYY86ZcMamE606dqdyjWlwhSHKOLUFsUUIzkMPz
1027KHRu/x3Yzi8+Hm8eFK/TnCbkpYsYw4hIw00176dYzaMtMCswDAYDVR0TAQH/BAIw
1028ADAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMA0GCSqGSIb3DQEBCwUAA4GB
1029AHvYzynIkjLThExHRS+385hfv4vgrQSMmCM1SAnEIjSBGsU7RPgiGAstN06XivuF
1030T1fNugRmTu4OtOIbfdYkcjavJufw9hR9zWTt77CNMTy9XmOZLgdS5boFTtLCztr3
1031TXHOSQQD8Dl4BK0wOet+TP6LBEjHlRFjAqK4bu9xpxV2
1032-----END CERTIFICATE-----
1033)";
Adam Langleybb507832019-09-17 12:56:01 -07001034
David Benjamin7fd831c2022-04-06 15:38:22 -04001035// CertFromPEM parses the given, NUL-terminated PEM block and returns an
Adam Langley3a39b062016-01-14 14:08:58 -08001036// |X509*|.
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001037static bssl::UniquePtr<X509> CertFromPEM(const char *pem) {
1038 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
1039 return bssl::UniquePtr<X509>(
1040 PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
David Benjamin93a69b42016-01-30 12:57:05 -05001041}
1042
David Benjamin7fd831c2022-04-06 15:38:22 -04001043// CRLFromPEM parses the given, NUL-terminated PEM block and returns an
Steven Valdezf9f312a2016-09-26 11:41:04 -04001044// |X509_CRL*|.
1045static bssl::UniquePtr<X509_CRL> CRLFromPEM(const char *pem) {
1046 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
1047 return bssl::UniquePtr<X509_CRL>(
1048 PEM_read_bio_X509_CRL(bio.get(), nullptr, nullptr, nullptr));
1049}
1050
David Benjamin7fd831c2022-04-06 15:38:22 -04001051// CSRFromPEM parses the given, NUL-terminated PEM block and returns an
1052// |X509_REQ*|.
1053static bssl::UniquePtr<X509_REQ> CSRFromPEM(const char *pem) {
1054 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
1055 return bssl::UniquePtr<X509_REQ>(
1056 PEM_read_bio_X509_REQ(bio.get(), nullptr, nullptr, nullptr));
1057}
1058
1059// PrivateKeyFromPEM parses the given, NUL-terminated PEM block and returns an
David Benjamin93a69b42016-01-30 12:57:05 -05001060// |EVP_PKEY*|.
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001061static bssl::UniquePtr<EVP_PKEY> PrivateKeyFromPEM(const char *pem) {
1062 bssl::UniquePtr<BIO> bio(
1063 BIO_new_mem_buf(const_cast<char *>(pem), strlen(pem)));
1064 return bssl::UniquePtr<EVP_PKEY>(
David Benjamin93a69b42016-01-30 12:57:05 -05001065 PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
Adam Langley3a39b062016-01-14 14:08:58 -08001066}
1067
David Benjamina7f56f02016-10-23 13:05:02 -04001068// CertsToStack converts a vector of |X509*| to an OpenSSL STACK_OF(X509),
Adam Langley3a39b062016-01-14 14:08:58 -08001069// bumping the reference counts for each certificate in question.
David Benjamina7f56f02016-10-23 13:05:02 -04001070static bssl::UniquePtr<STACK_OF(X509)> CertsToStack(
1071 const std::vector<X509 *> &certs) {
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001072 bssl::UniquePtr<STACK_OF(X509)> stack(sk_X509_new_null());
David Benjaminb7c5e842016-03-28 09:59:10 -04001073 if (!stack) {
1074 return nullptr;
1075 }
Adam Langley3a39b062016-01-14 14:08:58 -08001076 for (auto cert : certs) {
David Benjamin2908dd12018-06-29 17:46:42 -04001077 if (!bssl::PushToStack(stack.get(), bssl::UpRef(cert))) {
Adam Langley3a39b062016-01-14 14:08:58 -08001078 return nullptr;
1079 }
Adam Langley3a39b062016-01-14 14:08:58 -08001080 }
1081
David Benjamina7f56f02016-10-23 13:05:02 -04001082 return stack;
Adam Langley3a39b062016-01-14 14:08:58 -08001083}
1084
David Benjamina7f56f02016-10-23 13:05:02 -04001085// CRLsToStack converts a vector of |X509_CRL*| to an OpenSSL
1086// STACK_OF(X509_CRL), bumping the reference counts for each CRL in question.
1087static bssl::UniquePtr<STACK_OF(X509_CRL)> CRLsToStack(
1088 const std::vector<X509_CRL *> &crls) {
Steven Valdezf9f312a2016-09-26 11:41:04 -04001089 bssl::UniquePtr<STACK_OF(X509_CRL)> stack(sk_X509_CRL_new_null());
1090 if (!stack) {
1091 return nullptr;
1092 }
1093 for (auto crl : crls) {
David Benjamin2908dd12018-06-29 17:46:42 -04001094 if (!bssl::PushToStack(stack.get(), bssl::UpRef(crl))) {
Steven Valdezf9f312a2016-09-26 11:41:04 -04001095 return nullptr;
1096 }
Steven Valdezf9f312a2016-09-26 11:41:04 -04001097 }
1098
David Benjamina7f56f02016-10-23 13:05:02 -04001099 return stack;
Steven Valdezf9f312a2016-09-26 11:41:04 -04001100}
1101
David Benjamin04601b02021-08-24 15:11:58 -04001102static const time_t kReferenceTime = 1474934400 /* Sep 27th, 2016 */;
1103
David Benjamin8f5eb802021-10-01 16:40:31 -04001104static int Verify(
1105 X509 *leaf, const std::vector<X509 *> &roots,
1106 const std::vector<X509 *> &intermediates,
David Benjamin523d6c72021-10-01 16:56:12 -04001107 const std::vector<X509_CRL *> &crls, unsigned long flags = 0,
David Benjamin1f2529d2023-01-04 15:34:46 -08001108 std::function<void(X509_VERIFY_PARAM *)> configure_callback = nullptr) {
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001109 bssl::UniquePtr<STACK_OF(X509)> roots_stack(CertsToStack(roots));
1110 bssl::UniquePtr<STACK_OF(X509)> intermediates_stack(
1111 CertsToStack(intermediates));
Steven Valdezf9f312a2016-09-26 11:41:04 -04001112 bssl::UniquePtr<STACK_OF(X509_CRL)> crls_stack(CRLsToStack(crls));
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001113
Adam Langley3a39b062016-01-14 14:08:58 -08001114 if (!roots_stack ||
Steven Valdezf9f312a2016-09-26 11:41:04 -04001115 !intermediates_stack ||
1116 !crls_stack) {
1117 return X509_V_ERR_UNSPECIFIED;
Adam Langley3a39b062016-01-14 14:08:58 -08001118 }
1119
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001120 bssl::UniquePtr<X509_STORE_CTX> ctx(X509_STORE_CTX_new());
Steven Valdezf9f312a2016-09-26 11:41:04 -04001121 bssl::UniquePtr<X509_STORE> store(X509_STORE_new());
1122 if (!ctx ||
1123 !store) {
1124 return X509_V_ERR_UNSPECIFIED;
Adam Langley3a39b062016-01-14 14:08:58 -08001125 }
Steven Valdezf9f312a2016-09-26 11:41:04 -04001126
David Benjamin523d6c72021-10-01 16:56:12 -04001127 if (!X509_STORE_CTX_init(ctx.get(), store.get(), leaf,
1128 intermediates_stack.get())) {
Steven Valdezf9f312a2016-09-26 11:41:04 -04001129 return X509_V_ERR_UNSPECIFIED;
Adam Langley3a39b062016-01-14 14:08:58 -08001130 }
1131
David Benjamin2135ac62022-08-12 15:33:43 -04001132 X509_STORE_CTX_set0_trusted_stack(ctx.get(), roots_stack.get());
Steven Valdezf9f312a2016-09-26 11:41:04 -04001133 X509_STORE_CTX_set0_crls(ctx.get(), crls_stack.get());
Adam Langley3a39b062016-01-14 14:08:58 -08001134
David Benjamin2bde9362021-10-01 14:28:29 -04001135 X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx.get());
David Benjamin04601b02021-08-24 15:11:58 -04001136 X509_VERIFY_PARAM_set_time(param, kReferenceTime);
Adam Langley1902d812018-03-23 11:40:45 -07001137 if (configure_callback) {
1138 configure_callback(param);
1139 }
Adam Langley3a39b062016-01-14 14:08:58 -08001140 if (flags) {
1141 X509_VERIFY_PARAM_set_flags(param, flags);
1142 }
Adam Langley3a39b062016-01-14 14:08:58 -08001143
1144 ERR_clear_error();
Steven Valdezf9f312a2016-09-26 11:41:04 -04001145 if (X509_verify_cert(ctx.get()) != 1) {
1146 return X509_STORE_CTX_get_error(ctx.get());
1147 }
1148
1149 return X509_V_OK;
Adam Langley3a39b062016-01-14 14:08:58 -08001150}
1151
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001152TEST(X509Test, TestVerify) {
David Benjamin8f5eb802021-10-01 16:40:31 -04001153 // cross_signing_root
1154 // |
1155 // root_cross_signed root
1156 // \ /
1157 // intermediate
1158 // | |
1159 // leaf leaf_no_key_usage
1160 // |
1161 // forgery
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001162 bssl::UniquePtr<X509> cross_signing_root(CertFromPEM(kCrossSigningRootPEM));
1163 bssl::UniquePtr<X509> root(CertFromPEM(kRootCAPEM));
1164 bssl::UniquePtr<X509> root_cross_signed(CertFromPEM(kRootCrossSignedPEM));
1165 bssl::UniquePtr<X509> intermediate(CertFromPEM(kIntermediatePEM));
1166 bssl::UniquePtr<X509> intermediate_self_signed(
1167 CertFromPEM(kIntermediateSelfSignedPEM));
1168 bssl::UniquePtr<X509> leaf(CertFromPEM(kLeafPEM));
1169 bssl::UniquePtr<X509> leaf_no_key_usage(CertFromPEM(kLeafNoKeyUsagePEM));
1170 bssl::UniquePtr<X509> forgery(CertFromPEM(kForgeryPEM));
Adam Langley3a39b062016-01-14 14:08:58 -08001171
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001172 ASSERT_TRUE(cross_signing_root);
1173 ASSERT_TRUE(root);
1174 ASSERT_TRUE(root_cross_signed);
1175 ASSERT_TRUE(intermediate);
1176 ASSERT_TRUE(intermediate_self_signed);
1177 ASSERT_TRUE(leaf);
1178 ASSERT_TRUE(forgery);
1179 ASSERT_TRUE(leaf_no_key_usage);
Adam Langley3a39b062016-01-14 14:08:58 -08001180
David Benjamin8f5eb802021-10-01 16:40:31 -04001181 // Most of these tests work with or without |X509_V_FLAG_TRUSTED_FIRST|,
1182 // though in different ways.
1183 for (bool trusted_first : {true, false}) {
1184 SCOPED_TRACE(trusted_first);
1185 std::function<void(X509_VERIFY_PARAM *)> configure_callback;
1186 if (!trusted_first) {
1187 // Note we need the callback to clear the flag. Setting |flags| to zero
1188 // only skips setting new flags.
1189 configure_callback = [&](X509_VERIFY_PARAM *param) {
1190 X509_VERIFY_PARAM_clear_flags(param, X509_V_FLAG_TRUSTED_FIRST);
1191 };
1192 }
Adam Langley3a39b062016-01-14 14:08:58 -08001193
David Benjamin8f5eb802021-10-01 16:40:31 -04001194 // No trust anchors configured.
1195 ASSERT_EQ(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
1196 Verify(leaf.get(), /*roots=*/{}, /*intermediates=*/{},
1197 /*crls=*/{}, /*flags=*/0, configure_callback));
1198 ASSERT_EQ(
1199 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
1200 Verify(leaf.get(), /*roots=*/{}, {intermediate.get()}, /*crls=*/{},
1201 /*flags=*/0, configure_callback));
Adam Langley3a39b062016-01-14 14:08:58 -08001202
David Benjamin8f5eb802021-10-01 16:40:31 -04001203 // Each chain works individually.
1204 ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()},
1205 /*crls=*/{}, /*flags=*/0, configure_callback));
1206 ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {cross_signing_root.get()},
1207 {intermediate.get(), root_cross_signed.get()},
1208 /*crls=*/{}, /*flags=*/0, configure_callback));
Adam Langley3a39b062016-01-14 14:08:58 -08001209
David Benjamin8f5eb802021-10-01 16:40:31 -04001210 // When both roots are available, we pick one or the other.
1211 ASSERT_EQ(X509_V_OK,
1212 Verify(leaf.get(), {cross_signing_root.get(), root.get()},
1213 {intermediate.get(), root_cross_signed.get()}, /*crls=*/{},
1214 /*flags=*/0, configure_callback));
1215
1216 // This is the “altchains” test – we remove the cross-signing CA but include
1217 // the cross-sign in the intermediates. With |trusted_first|, we
1218 // preferentially stop path-building at |intermediate|. Without
1219 // |trusted_first|, the "altchains" logic repairs it.
1220 ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()},
1221 {intermediate.get(), root_cross_signed.get()},
1222 /*crls=*/{}, /*flags=*/0, configure_callback));
1223
1224 // If |X509_V_FLAG_NO_ALT_CHAINS| is set and |trusted_first| is disabled, we
1225 // get stuck on |root_cross_signed|. If either feature is enabled, we can
1226 // build the path.
1227 //
1228 // This test exists to confirm our current behavior, but these modes are
1229 // just workarounds for not having an actual path-building verifier. If we
1230 // fix it, this test can be removed.
1231 ASSERT_EQ(trusted_first ? X509_V_OK
1232 : X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
1233 Verify(leaf.get(), {root.get()},
1234 {intermediate.get(), root_cross_signed.get()}, /*crls=*/{},
1235 /*flags=*/X509_V_FLAG_NO_ALT_CHAINS, configure_callback));
1236
1237 // |forgery| is signed by |leaf_no_key_usage|, but is rejected because the
1238 // leaf is not a CA.
1239 ASSERT_EQ(X509_V_ERR_INVALID_CA,
1240 Verify(forgery.get(), {intermediate_self_signed.get()},
1241 {leaf_no_key_usage.get()}, /*crls=*/{}, /*flags=*/0,
1242 configure_callback));
1243
1244 // Test that one cannot skip Basic Constraints checking with a contorted set
1245 // of roots and intermediates. This is a regression test for CVE-2015-1793.
1246 ASSERT_EQ(X509_V_ERR_INVALID_CA,
1247 Verify(forgery.get(),
1248 {intermediate_self_signed.get(), root_cross_signed.get()},
1249 {leaf_no_key_usage.get(), intermediate.get()}, /*crls=*/{},
1250 /*flags=*/0, configure_callback));
1251 }
Adam Langley1902d812018-03-23 11:40:45 -07001252}
Adam Langleye759a9c2018-03-22 10:02:54 -07001253
David Benjamin030693d2022-12-13 13:23:07 -05001254#if defined(OPENSSL_THREADS)
1255// Verifying the same |X509| objects on two threads should be safe.
1256TEST(X509Test, VerifyThreads) {
1257 bssl::UniquePtr<X509> root(CertFromPEM(kRootCAPEM));
1258 bssl::UniquePtr<X509> intermediate(CertFromPEM(kIntermediatePEM));
1259 bssl::UniquePtr<X509> leaf(CertFromPEM(kLeafPEM));
1260 ASSERT_TRUE(root);
1261 ASSERT_TRUE(intermediate);
1262 ASSERT_TRUE(leaf);
1263
1264 const size_t kNumThreads = 10;
1265 std::vector<std::thread> threads;
1266 for (size_t i = 0; i < kNumThreads; i++) {
1267 threads.emplace_back([&] {
1268 EXPECT_EQ(X509_V_OK,
1269 Verify(leaf.get(), {root.get()}, {intermediate.get()},
1270 /*crls=*/{}));
1271 });
1272 }
1273 for (auto &thread : threads) {
1274 thread.join();
1275 }
1276}
1277#endif // OPENSSL_THREADS
1278
Adam Langley1902d812018-03-23 11:40:45 -07001279static const char kHostname[] = "example.com";
1280static const char kWrongHostname[] = "example2.com";
1281static const char kEmail[] = "test@example.com";
1282static const char kWrongEmail[] = "test2@example.com";
1283static const uint8_t kIP[4] = {127, 0, 0, 1};
1284static const uint8_t kWrongIP[4] = {127, 0, 0, 2};
1285static const char kIPString[] = "127.0.0.1";
1286static const char kWrongIPString[] = "127.0.0.2";
1287
1288TEST(X509Test, ZeroLengthsWithX509PARAM) {
1289 bssl::UniquePtr<X509> leaf(CertFromPEM(kSANTypesLeaf));
1290 bssl::UniquePtr<X509> root(CertFromPEM(kSANTypesRoot));
1291 ASSERT_TRUE(leaf);
1292 ASSERT_TRUE(root);
1293
1294 std::vector<X509_CRL *> empty_crls;
1295
Daniel Hirchee6737a82018-05-15 14:08:24 +02001296 struct X509Test {
Adam Langley1902d812018-03-23 11:40:45 -07001297 const char *correct_value;
1298 size_t correct_value_len;
1299 const char *incorrect_value;
1300 size_t incorrect_value_len;
1301 int (*func)(X509_VERIFY_PARAM *, const char *, size_t);
1302 int mismatch_error;
1303 };
Daniel Hirchee6737a82018-05-15 14:08:24 +02001304 const std::vector<X509Test> kTests = {
Adam Langley1902d812018-03-23 11:40:45 -07001305 {kHostname, strlen(kHostname), kWrongHostname, strlen(kWrongHostname),
1306 X509_VERIFY_PARAM_set1_host, X509_V_ERR_HOSTNAME_MISMATCH},
1307 {kEmail, strlen(kEmail), kWrongEmail, strlen(kWrongEmail),
1308 X509_VERIFY_PARAM_set1_email, X509_V_ERR_EMAIL_MISMATCH},
1309 };
1310
1311 for (size_t i = 0; i < kTests.size(); i++) {
1312 SCOPED_TRACE(i);
Daniel Hirchee6737a82018-05-15 14:08:24 +02001313 const X509Test &test = kTests[i];
Adam Langley1902d812018-03-23 11:40:45 -07001314
1315 // The correct value should work.
1316 ASSERT_EQ(X509_V_OK,
David Benjamin523d6c72021-10-01 16:56:12 -04001317 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001318 [&test](X509_VERIFY_PARAM *param) {
1319 ASSERT_TRUE(test.func(param, test.correct_value,
1320 test.correct_value_len));
1321 }));
1322
1323 // The wrong value should trigger a verification error.
1324 ASSERT_EQ(test.mismatch_error,
David Benjamin523d6c72021-10-01 16:56:12 -04001325 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001326 [&test](X509_VERIFY_PARAM *param) {
1327 ASSERT_TRUE(test.func(param, test.incorrect_value,
1328 test.incorrect_value_len));
1329 }));
1330
1331 // Passing zero as the length, unlike OpenSSL, should trigger an error and
1332 // should cause verification to fail.
1333 ASSERT_EQ(X509_V_ERR_INVALID_CALL,
David Benjamin523d6c72021-10-01 16:56:12 -04001334 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001335 [&test](X509_VERIFY_PARAM *param) {
1336 ASSERT_FALSE(test.func(param, test.correct_value, 0));
1337 }));
1338
1339 // Passing an empty value should be an error when setting and should cause
1340 // verification to fail.
1341 ASSERT_EQ(X509_V_ERR_INVALID_CALL,
David Benjamin523d6c72021-10-01 16:56:12 -04001342 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001343 [&test](X509_VERIFY_PARAM *param) {
1344 ASSERT_FALSE(test.func(param, nullptr, 0));
1345 }));
1346
1347 // Passing a value with embedded NULs should also be an error and should
1348 // also cause verification to fail.
1349 ASSERT_EQ(X509_V_ERR_INVALID_CALL,
David Benjamin523d6c72021-10-01 16:56:12 -04001350 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001351 [&test](X509_VERIFY_PARAM *param) {
1352 ASSERT_FALSE(test.func(param, "a", 2));
1353 }));
1354 }
1355
1356 // IP addresses work slightly differently:
1357
1358 // The correct value should still work.
1359 ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
David Benjamin523d6c72021-10-01 16:56:12 -04001360 [](X509_VERIFY_PARAM *param) {
Adam Langley1902d812018-03-23 11:40:45 -07001361 ASSERT_TRUE(X509_VERIFY_PARAM_set1_ip(
1362 param, kIP, sizeof(kIP)));
1363 }));
1364
1365 // Incorrect values should still fail.
1366 ASSERT_EQ(X509_V_ERR_IP_ADDRESS_MISMATCH,
David Benjamin523d6c72021-10-01 16:56:12 -04001367 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001368 [](X509_VERIFY_PARAM *param) {
1369 ASSERT_TRUE(X509_VERIFY_PARAM_set1_ip(param, kWrongIP,
1370 sizeof(kWrongIP)));
1371 }));
1372
1373 // Zero length values should trigger an error when setting and cause
1374 // verification to always fail.
1375 ASSERT_EQ(X509_V_ERR_INVALID_CALL,
David Benjamin523d6c72021-10-01 16:56:12 -04001376 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001377 [](X509_VERIFY_PARAM *param) {
1378 ASSERT_FALSE(X509_VERIFY_PARAM_set1_ip(param, kIP, 0));
1379 }));
1380
1381 // ... and so should NULL values.
1382 ASSERT_EQ(X509_V_ERR_INVALID_CALL,
David Benjamin523d6c72021-10-01 16:56:12 -04001383 Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
Adam Langley1902d812018-03-23 11:40:45 -07001384 [](X509_VERIFY_PARAM *param) {
1385 ASSERT_FALSE(X509_VERIFY_PARAM_set1_ip(param, nullptr, 0));
1386 }));
1387
1388 // Zero bytes in an IP address are, of course, fine. This is tested above
1389 // because |kIP| contains zeros.
1390}
1391
1392TEST(X509Test, ZeroLengthsWithCheckFunctions) {
1393 bssl::UniquePtr<X509> leaf(CertFromPEM(kSANTypesLeaf));
1394
1395 EXPECT_EQ(
1396 1, X509_check_host(leaf.get(), kHostname, strlen(kHostname), 0, nullptr));
1397 EXPECT_NE(1, X509_check_host(leaf.get(), kWrongHostname,
1398 strlen(kWrongHostname), 0, nullptr));
1399
1400 EXPECT_EQ(1, X509_check_email(leaf.get(), kEmail, strlen(kEmail), 0));
1401 EXPECT_NE(1,
1402 X509_check_email(leaf.get(), kWrongEmail, strlen(kWrongEmail), 0));
1403
1404 EXPECT_EQ(1, X509_check_ip(leaf.get(), kIP, sizeof(kIP), 0));
1405 EXPECT_NE(1, X509_check_ip(leaf.get(), kWrongIP, sizeof(kWrongIP), 0));
1406
1407 EXPECT_EQ(1, X509_check_ip_asc(leaf.get(), kIPString, 0));
1408 EXPECT_NE(1, X509_check_ip_asc(leaf.get(), kWrongIPString, 0));
1409
1410 // OpenSSL supports passing zero as the length for host and email. We do not
1411 // and it should always fail.
1412 EXPECT_NE(1, X509_check_host(leaf.get(), kHostname, 0, 0, nullptr));
1413 EXPECT_NE(1, X509_check_host(leaf.get(), kWrongHostname, 0, 0, nullptr));
1414
1415 EXPECT_NE(1, X509_check_email(leaf.get(), kEmail, 0, 0));
1416 EXPECT_NE(1, X509_check_email(leaf.get(), kWrongEmail, 0, 0));
1417
1418 EXPECT_NE(1, X509_check_ip(leaf.get(), kIP, 0, 0));
1419 EXPECT_NE(1, X509_check_ip(leaf.get(), kWrongIP, 0, 0));
1420
1421 // Unlike all the other functions, |X509_check_ip_asc| doesn't take a length,
1422 // so it cannot be zero.
David Benjamin93a69b42016-01-30 12:57:05 -05001423}
1424
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001425TEST(X509Test, TestCRL) {
Steven Valdezf9f312a2016-09-26 11:41:04 -04001426 bssl::UniquePtr<X509> root(CertFromPEM(kCRLTestRoot));
1427 bssl::UniquePtr<X509> leaf(CertFromPEM(kCRLTestLeaf));
1428 bssl::UniquePtr<X509_CRL> basic_crl(CRLFromPEM(kBasicCRL));
1429 bssl::UniquePtr<X509_CRL> revoked_crl(CRLFromPEM(kRevokedCRL));
1430 bssl::UniquePtr<X509_CRL> bad_issuer_crl(CRLFromPEM(kBadIssuerCRL));
David Benjaminbe941d42016-10-22 13:55:05 -04001431 bssl::UniquePtr<X509_CRL> known_critical_crl(CRLFromPEM(kKnownCriticalCRL));
1432 bssl::UniquePtr<X509_CRL> unknown_critical_crl(
1433 CRLFromPEM(kUnknownCriticalCRL));
1434 bssl::UniquePtr<X509_CRL> unknown_critical_crl2(
1435 CRLFromPEM(kUnknownCriticalCRL2));
David Benjamineb5640b2021-02-26 01:14:47 -05001436 bssl::UniquePtr<X509_CRL> algorithm_mismatch_crl(
1437 CRLFromPEM(kAlgorithmMismatchCRL));
1438 bssl::UniquePtr<X509_CRL> algorithm_mismatch_crl2(
1439 CRLFromPEM(kAlgorithmMismatchCRL2));
Steven Valdezf9f312a2016-09-26 11:41:04 -04001440
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001441 ASSERT_TRUE(root);
1442 ASSERT_TRUE(leaf);
1443 ASSERT_TRUE(basic_crl);
1444 ASSERT_TRUE(revoked_crl);
1445 ASSERT_TRUE(bad_issuer_crl);
1446 ASSERT_TRUE(known_critical_crl);
1447 ASSERT_TRUE(unknown_critical_crl);
1448 ASSERT_TRUE(unknown_critical_crl2);
David Benjamineb5640b2021-02-26 01:14:47 -05001449 ASSERT_TRUE(algorithm_mismatch_crl);
1450 ASSERT_TRUE(algorithm_mismatch_crl2);
Steven Valdezf9f312a2016-09-26 11:41:04 -04001451
David Benjamineb5640b2021-02-26 01:14:47 -05001452 EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {root.get()},
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001453 {basic_crl.get()}, X509_V_FLAG_CRL_CHECK));
David Benjamineb5640b2021-02-26 01:14:47 -05001454 EXPECT_EQ(
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001455 X509_V_ERR_CERT_REVOKED,
1456 Verify(leaf.get(), {root.get()}, {root.get()},
1457 {basic_crl.get(), revoked_crl.get()}, X509_V_FLAG_CRL_CHECK));
Steven Valdezf9f312a2016-09-26 11:41:04 -04001458
David Benjamindaf4a052016-09-27 13:55:57 -04001459 std::vector<X509_CRL *> empty_crls;
David Benjamineb5640b2021-02-26 01:14:47 -05001460 EXPECT_EQ(X509_V_ERR_UNABLE_TO_GET_CRL,
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001461 Verify(leaf.get(), {root.get()}, {root.get()}, empty_crls,
1462 X509_V_FLAG_CRL_CHECK));
David Benjamineb5640b2021-02-26 01:14:47 -05001463 EXPECT_EQ(X509_V_ERR_UNABLE_TO_GET_CRL,
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001464 Verify(leaf.get(), {root.get()}, {root.get()},
1465 {bad_issuer_crl.get()}, X509_V_FLAG_CRL_CHECK));
David Benjamineb5640b2021-02-26 01:14:47 -05001466 EXPECT_EQ(X509_V_OK,
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001467 Verify(leaf.get(), {root.get()}, {root.get()},
1468 {known_critical_crl.get()}, X509_V_FLAG_CRL_CHECK));
David Benjamineb5640b2021-02-26 01:14:47 -05001469 EXPECT_EQ(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001470 Verify(leaf.get(), {root.get()}, {root.get()},
1471 {unknown_critical_crl.get()}, X509_V_FLAG_CRL_CHECK));
David Benjamineb5640b2021-02-26 01:14:47 -05001472 EXPECT_EQ(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001473 Verify(leaf.get(), {root.get()}, {root.get()},
1474 {unknown_critical_crl2.get()}, X509_V_FLAG_CRL_CHECK));
David Benjamineb5640b2021-02-26 01:14:47 -05001475 EXPECT_EQ(X509_V_ERR_CRL_SIGNATURE_FAILURE,
1476 Verify(leaf.get(), {root.get()}, {root.get()},
1477 {algorithm_mismatch_crl.get()}, X509_V_FLAG_CRL_CHECK));
1478 EXPECT_EQ(X509_V_ERR_CRL_SIGNATURE_FAILURE,
1479 Verify(leaf.get(), {root.get()}, {root.get()},
1480 {algorithm_mismatch_crl2.get()}, X509_V_FLAG_CRL_CHECK));
David Benjaminfd86eaa2020-06-17 15:13:16 -04001481
David Benjamineccd1032022-08-12 15:12:29 -04001482 // The CRL is valid for a month.
1483 EXPECT_EQ(X509_V_ERR_CRL_HAS_EXPIRED,
1484 Verify(leaf.get(), {root.get()}, {root.get()}, {basic_crl.get()},
1485 X509_V_FLAG_CRL_CHECK, [](X509_VERIFY_PARAM *param) {
1486 X509_VERIFY_PARAM_set_time(
1487 param, kReferenceTime + 2 * 30 * 24 * 3600);
1488 }));
1489
1490 // X509_V_FLAG_NO_CHECK_TIME suppresses the validity check.
1491 EXPECT_EQ(X509_V_OK,
1492 Verify(leaf.get(), {root.get()}, {root.get()}, {basic_crl.get()},
1493 X509_V_FLAG_CRL_CHECK | X509_V_FLAG_NO_CHECK_TIME,
1494 [](X509_VERIFY_PARAM *param) {
1495 X509_VERIFY_PARAM_set_time(
1496 param, kReferenceTime + 2 * 30 * 24 * 3600);
1497 }));
1498
David Benjaminfd86eaa2020-06-17 15:13:16 -04001499 // Parsing kBadExtensionCRL should fail.
1500 EXPECT_FALSE(CRLFromPEM(kBadExtensionCRL));
Steven Valdezf9f312a2016-09-26 11:41:04 -04001501}
1502
David Benjamin40150002017-09-18 18:22:01 -04001503TEST(X509Test, ManyNamesAndConstraints) {
David Benjamin5ddc5b12020-06-17 14:07:25 -04001504 bssl::UniquePtr<X509> many_constraints(CertFromPEM(
1505 GetTestData("crypto/x509/test/many_constraints.pem").c_str()));
David Benjamin40150002017-09-18 18:22:01 -04001506 ASSERT_TRUE(many_constraints);
1507 bssl::UniquePtr<X509> many_names1(
David Benjamin5ddc5b12020-06-17 14:07:25 -04001508 CertFromPEM(GetTestData("crypto/x509/test/many_names1.pem").c_str()));
David Benjamin40150002017-09-18 18:22:01 -04001509 ASSERT_TRUE(many_names1);
1510 bssl::UniquePtr<X509> many_names2(
David Benjamin5ddc5b12020-06-17 14:07:25 -04001511 CertFromPEM(GetTestData("crypto/x509/test/many_names2.pem").c_str()));
David Benjamin40150002017-09-18 18:22:01 -04001512 ASSERT_TRUE(many_names2);
1513 bssl::UniquePtr<X509> many_names3(
David Benjamin5ddc5b12020-06-17 14:07:25 -04001514 CertFromPEM(GetTestData("crypto/x509/test/many_names3.pem").c_str()));
David Benjamin40150002017-09-18 18:22:01 -04001515 ASSERT_TRUE(many_names3);
1516 bssl::UniquePtr<X509> some_names1(
David Benjamin5ddc5b12020-06-17 14:07:25 -04001517 CertFromPEM(GetTestData("crypto/x509/test/some_names1.pem").c_str()));
David Benjamin40150002017-09-18 18:22:01 -04001518 ASSERT_TRUE(some_names1);
1519 bssl::UniquePtr<X509> some_names2(
David Benjamin5ddc5b12020-06-17 14:07:25 -04001520 CertFromPEM(GetTestData("crypto/x509/test/some_names2.pem").c_str()));
David Benjamin40150002017-09-18 18:22:01 -04001521 ASSERT_TRUE(some_names2);
1522 bssl::UniquePtr<X509> some_names3(
David Benjamin5ddc5b12020-06-17 14:07:25 -04001523 CertFromPEM(GetTestData("crypto/x509/test/some_names3.pem").c_str()));
David Benjamin40150002017-09-18 18:22:01 -04001524 ASSERT_TRUE(some_names3);
1525
1526 EXPECT_EQ(X509_V_ERR_UNSPECIFIED,
1527 Verify(many_names1.get(), {many_constraints.get()},
1528 {many_constraints.get()}, {}));
1529 EXPECT_EQ(X509_V_ERR_UNSPECIFIED,
1530 Verify(many_names2.get(), {many_constraints.get()},
1531 {many_constraints.get()}, {}));
1532 EXPECT_EQ(X509_V_ERR_UNSPECIFIED,
1533 Verify(many_names3.get(), {many_constraints.get()},
1534 {many_constraints.get()}, {}));
1535
1536 EXPECT_EQ(X509_V_OK, Verify(some_names1.get(), {many_constraints.get()},
1537 {many_constraints.get()}, {}));
1538 EXPECT_EQ(X509_V_OK, Verify(some_names2.get(), {many_constraints.get()},
1539 {many_constraints.get()}, {}));
1540 EXPECT_EQ(X509_V_OK, Verify(some_names3.get(), {many_constraints.get()},
1541 {many_constraints.get()}, {}));
1542}
1543
David Benjamin04601b02021-08-24 15:11:58 -04001544static bssl::UniquePtr<GENERAL_NAME> MakeGeneralName(int type,
1545 const std::string &value) {
1546 if (type != GEN_EMAIL && type != GEN_DNS && type != GEN_URI) {
1547 // This function only supports the IA5String types.
1548 return nullptr;
1549 }
1550 bssl::UniquePtr<ASN1_IA5STRING> str(ASN1_IA5STRING_new());
1551 bssl::UniquePtr<GENERAL_NAME> name(GENERAL_NAME_new());
1552 if (!str || !name ||
1553 !ASN1_STRING_set(str.get(), value.data(), value.size())) {
1554 return nullptr;
1555 }
1556
1557 name->type = type;
1558 name->d.ia5 = str.release();
1559 return name;
1560}
1561
1562static bssl::UniquePtr<X509> MakeTestCert(const char *issuer,
David Benjamin8f5eb802021-10-01 16:40:31 -04001563 const char *subject, EVP_PKEY *key,
1564 bool is_ca) {
David Benjamin04601b02021-08-24 15:11:58 -04001565 bssl::UniquePtr<X509> cert(X509_new());
1566 if (!cert || //
1567 !X509_set_version(cert.get(), X509_VERSION_3) ||
1568 !X509_NAME_add_entry_by_txt(
1569 X509_get_issuer_name(cert.get()), "CN", MBSTRING_UTF8,
1570 reinterpret_cast<const uint8_t *>(issuer), -1, -1, 0) ||
1571 !X509_NAME_add_entry_by_txt(
1572 X509_get_subject_name(cert.get()), "CN", MBSTRING_UTF8,
1573 reinterpret_cast<const uint8_t *>(subject), -1, -1, 0) ||
1574 !X509_set_pubkey(cert.get(), key) ||
1575 !ASN1_TIME_adj(X509_getm_notBefore(cert.get()), kReferenceTime, -1, 0) ||
1576 !ASN1_TIME_adj(X509_getm_notAfter(cert.get()), kReferenceTime, 1, 0)) {
1577 return nullptr;
1578 }
David Benjamin8f5eb802021-10-01 16:40:31 -04001579 bssl::UniquePtr<BASIC_CONSTRAINTS> bc(BASIC_CONSTRAINTS_new());
1580 if (!bc) {
1581 return nullptr;
1582 }
1583 bc->ca = is_ca ? 0xff : 0x00;
1584 if (!X509_add1_ext_i2d(cert.get(), NID_basic_constraints, bc.get(),
1585 /*crit=*/1, /*flags=*/0)) {
1586 return nullptr;
1587 }
David Benjamin04601b02021-08-24 15:11:58 -04001588 return cert;
1589}
1590
1591TEST(X509Test, NameConstraints) {
1592 bssl::UniquePtr<EVP_PKEY> key = PrivateKeyFromPEM(kP256Key);
1593 ASSERT_TRUE(key);
1594
1595 const struct {
1596 int type;
1597 std::string name;
1598 std::string constraint;
1599 int result;
1600 } kTests[] = {
1601 // Empty string matches everything.
1602 {GEN_DNS, "foo.example.com", "", X509_V_OK},
1603 // Name constraints match the entire subtree.
1604 {GEN_DNS, "foo.example.com", "example.com", X509_V_OK},
1605 {GEN_DNS, "foo.example.com", "EXAMPLE.COM", X509_V_OK},
1606 {GEN_DNS, "foo.example.com", "xample.com",
1607 X509_V_ERR_PERMITTED_VIOLATION},
1608 {GEN_DNS, "foo.example.com", "unrelated.much.longer.name.example",
1609 X509_V_ERR_PERMITTED_VIOLATION},
1610 // A leading dot means at least one component must be added.
1611 {GEN_DNS, "foo.example.com", ".example.com", X509_V_OK},
1612 {GEN_DNS, "foo.example.com", "foo.example.com", X509_V_OK},
1613 {GEN_DNS, "foo.example.com", ".foo.example.com",
1614 X509_V_ERR_PERMITTED_VIOLATION},
1615 {GEN_DNS, "foo.example.com", ".xample.com",
1616 X509_V_ERR_PERMITTED_VIOLATION},
1617 {GEN_DNS, "foo.example.com", ".unrelated.much.longer.name.example",
1618 X509_V_ERR_PERMITTED_VIOLATION},
David Benjaminb27438e2021-08-24 14:24:38 -04001619 // NUL bytes, if not rejected, should not confuse the matching logic.
1620 {GEN_DNS, std::string({'a', '\0', 'a'}), std::string({'a', '\0', 'b'}),
1621 X509_V_ERR_PERMITTED_VIOLATION},
David Benjamin04601b02021-08-24 15:11:58 -04001622
1623 // Names must be emails.
1624 {GEN_EMAIL, "not-an-email.example", "not-an-email.example",
1625 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX},
1626 // A leading dot matches all local names and all subdomains
1627 {GEN_EMAIL, "foo@bar.example.com", ".example.com", X509_V_OK},
1628 {GEN_EMAIL, "foo@bar.example.com", ".EXAMPLE.COM", X509_V_OK},
1629 {GEN_EMAIL, "foo@bar.example.com", ".bar.example.com",
1630 X509_V_ERR_PERMITTED_VIOLATION},
1631 // Without a leading dot, the host must match exactly.
1632 {GEN_EMAIL, "foo@example.com", "example.com", X509_V_OK},
1633 {GEN_EMAIL, "foo@example.com", "EXAMPLE.COM", X509_V_OK},
1634 {GEN_EMAIL, "foo@bar.example.com", "example.com",
1635 X509_V_ERR_PERMITTED_VIOLATION},
1636 // If the constraint specifies a mailbox, it specifies the whole thing.
1637 // The halves are compared insensitively.
1638 {GEN_EMAIL, "foo@example.com", "foo@example.com", X509_V_OK},
1639 {GEN_EMAIL, "foo@example.com", "foo@EXAMPLE.COM", X509_V_OK},
1640 {GEN_EMAIL, "foo@example.com", "FOO@example.com",
1641 X509_V_ERR_PERMITTED_VIOLATION},
1642 {GEN_EMAIL, "foo@example.com", "bar@example.com",
1643 X509_V_ERR_PERMITTED_VIOLATION},
1644 // OpenSSL ignores a stray leading @.
1645 {GEN_EMAIL, "foo@example.com", "@example.com", X509_V_OK},
1646 {GEN_EMAIL, "foo@example.com", "@EXAMPLE.COM", X509_V_OK},
1647 {GEN_EMAIL, "foo@bar.example.com", "@example.com",
1648 X509_V_ERR_PERMITTED_VIOLATION},
1649
1650 // Basic syntax check.
1651 {GEN_URI, "not-a-url", "not-a-url", X509_V_ERR_UNSUPPORTED_NAME_SYNTAX},
1652 {GEN_URI, "foo:not-a-url", "not-a-url",
1653 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX},
1654 {GEN_URI, "foo:/not-a-url", "not-a-url",
1655 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX},
1656 {GEN_URI, "foo:///not-a-url", "not-a-url",
1657 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX},
1658 {GEN_URI, "foo://:not-a-url", "not-a-url",
1659 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX},
1660 {GEN_URI, "foo://", "not-a-url", X509_V_ERR_UNSUPPORTED_NAME_SYNTAX},
1661 // Hosts are an exact match.
1662 {GEN_URI, "foo://example.com", "example.com", X509_V_OK},
1663 {GEN_URI, "foo://example.com:443", "example.com", X509_V_OK},
1664 {GEN_URI, "foo://example.com/whatever", "example.com", X509_V_OK},
1665 {GEN_URI, "foo://bar.example.com", "example.com",
1666 X509_V_ERR_PERMITTED_VIOLATION},
1667 {GEN_URI, "foo://bar.example.com:443", "example.com",
1668 X509_V_ERR_PERMITTED_VIOLATION},
1669 {GEN_URI, "foo://bar.example.com/whatever", "example.com",
1670 X509_V_ERR_PERMITTED_VIOLATION},
1671 {GEN_URI, "foo://bar.example.com", "xample.com",
1672 X509_V_ERR_PERMITTED_VIOLATION},
1673 {GEN_URI, "foo://bar.example.com:443", "xample.com",
1674 X509_V_ERR_PERMITTED_VIOLATION},
1675 {GEN_URI, "foo://bar.example.com/whatever", "xample.com",
1676 X509_V_ERR_PERMITTED_VIOLATION},
1677 {GEN_URI, "foo://example.com", "some-other-name.example",
1678 X509_V_ERR_PERMITTED_VIOLATION},
1679 {GEN_URI, "foo://example.com:443", "some-other-name.example",
1680 X509_V_ERR_PERMITTED_VIOLATION},
1681 {GEN_URI, "foo://example.com/whatever", "some-other-name.example",
1682 X509_V_ERR_PERMITTED_VIOLATION},
1683 // A leading dot allows components to be added.
1684 {GEN_URI, "foo://example.com", ".example.com",
1685 X509_V_ERR_PERMITTED_VIOLATION},
1686 {GEN_URI, "foo://example.com:443", ".example.com",
1687 X509_V_ERR_PERMITTED_VIOLATION},
1688 {GEN_URI, "foo://example.com/whatever", ".example.com",
1689 X509_V_ERR_PERMITTED_VIOLATION},
1690 {GEN_URI, "foo://bar.example.com", ".example.com", X509_V_OK},
1691 {GEN_URI, "foo://bar.example.com:443", ".example.com", X509_V_OK},
1692 {GEN_URI, "foo://bar.example.com/whatever", ".example.com", X509_V_OK},
1693 {GEN_URI, "foo://example.com", ".some-other-name.example",
1694 X509_V_ERR_PERMITTED_VIOLATION},
1695 {GEN_URI, "foo://example.com:443", ".some-other-name.example",
1696 X509_V_ERR_PERMITTED_VIOLATION},
1697 {GEN_URI, "foo://example.com/whatever", ".some-other-name.example",
1698 X509_V_ERR_PERMITTED_VIOLATION},
1699 {GEN_URI, "foo://example.com", ".xample.com",
1700 X509_V_ERR_PERMITTED_VIOLATION},
1701 {GEN_URI, "foo://example.com:443", ".xample.com",
1702 X509_V_ERR_PERMITTED_VIOLATION},
1703 {GEN_URI, "foo://example.com/whatever", ".xample.com",
1704 X509_V_ERR_PERMITTED_VIOLATION},
1705 };
1706 for (const auto &t : kTests) {
1707 SCOPED_TRACE(t.type);
1708 SCOPED_TRACE(t.name);
1709 SCOPED_TRACE(t.constraint);
1710
1711 bssl::UniquePtr<GENERAL_NAME> name = MakeGeneralName(t.type, t.name);
1712 ASSERT_TRUE(name);
1713 bssl::UniquePtr<GENERAL_NAMES> names(GENERAL_NAMES_new());
1714 ASSERT_TRUE(names);
1715 ASSERT_TRUE(bssl::PushToStack(names.get(), std::move(name)));
1716
1717 bssl::UniquePtr<NAME_CONSTRAINTS> nc(NAME_CONSTRAINTS_new());
1718 ASSERT_TRUE(nc);
1719 nc->permittedSubtrees = sk_GENERAL_SUBTREE_new_null();
1720 ASSERT_TRUE(nc->permittedSubtrees);
1721 bssl::UniquePtr<GENERAL_SUBTREE> subtree(GENERAL_SUBTREE_new());
1722 ASSERT_TRUE(subtree);
1723 GENERAL_NAME_free(subtree->base);
1724 subtree->base = MakeGeneralName(t.type, t.constraint).release();
1725 ASSERT_TRUE(subtree->base);
1726 ASSERT_TRUE(bssl::PushToStack(nc->permittedSubtrees, std::move(subtree)));
1727
David Benjamin8f5eb802021-10-01 16:40:31 -04001728 bssl::UniquePtr<X509> root =
1729 MakeTestCert("Root", "Root", key.get(), /*is_ca=*/true);
David Benjamin04601b02021-08-24 15:11:58 -04001730 ASSERT_TRUE(root);
1731 ASSERT_TRUE(X509_add1_ext_i2d(root.get(), NID_name_constraints, nc.get(),
1732 /*crit=*/1, /*flags=*/0));
1733 ASSERT_TRUE(X509_sign(root.get(), key.get(), EVP_sha256()));
1734
David Benjamin8f5eb802021-10-01 16:40:31 -04001735 bssl::UniquePtr<X509> leaf =
1736 MakeTestCert("Root", "Leaf", key.get(), /*is_ca=*/false);
David Benjamin04601b02021-08-24 15:11:58 -04001737 ASSERT_TRUE(leaf);
1738 ASSERT_TRUE(X509_add1_ext_i2d(leaf.get(), NID_subject_alt_name, names.get(),
1739 /*crit=*/0, /*flags=*/0));
1740 ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256()));
1741
1742 int ret = Verify(leaf.get(), {root.get()}, {}, {}, 0);
1743 EXPECT_EQ(t.result, ret) << X509_verify_cert_error_string(ret);
1744 }
1745}
1746
David Benjamin4bf0a192021-08-25 11:23:51 -04001747TEST(X509Test, PrintGeneralName) {
1748 // TODO(https://crbug.com/boringssl/430): Add more tests. Also fix the
1749 // external projects that use this to extract the SAN list and unexport.
1750 bssl::UniquePtr<GENERAL_NAME> gen = MakeGeneralName(GEN_DNS, "example.com");
1751 ASSERT_TRUE(gen);
1752 bssl::UniquePtr<STACK_OF(CONF_VALUE)> values(
1753 i2v_GENERAL_NAME(nullptr, gen.get(), nullptr));
1754 ASSERT_TRUE(values);
1755 ASSERT_EQ(1u, sk_CONF_VALUE_num(values.get()));
1756 const CONF_VALUE *value = sk_CONF_VALUE_value(values.get(), 0);
1757 EXPECT_STREQ(value->name, "DNS");
1758 EXPECT_STREQ(value->value, "example.com");
1759}
1760
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001761TEST(X509Test, TestPSS) {
David Benjamina6d321b2022-08-03 18:36:25 -04001762 static const char *kGoodCerts[] = {
1763 "crypto/x509/test/pss_sha256.pem",
1764 "crypto/x509/test/pss_sha384.pem",
1765 "crypto/x509/test/pss_sha512.pem",
1766 // We accept inputs with and without explicit NULLs. See RFC 4055,
1767 // section 2.1.
1768 "crypto/x509/test/pss_sha256_omit_nulls.pem",
1769 // Although invalid, we tolerate an explicit trailerField value. See the
1770 // certificates in cl/362617931.
1771 "crypto/x509/test/pss_sha256_explicit_trailer.pem",
1772 };
1773 for (const char *path : kGoodCerts) {
1774 SCOPED_TRACE(path);
1775 bssl::UniquePtr<X509> cert = CertFromPEM(GetTestData(path).c_str());
1776 ASSERT_TRUE(cert);
1777 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
1778 ASSERT_TRUE(pkey);
1779 EXPECT_TRUE(X509_verify(cert.get(), pkey.get()));
1780 }
David Benjamin93a69b42016-01-30 12:57:05 -05001781
David Benjamina6d321b2022-08-03 18:36:25 -04001782 static const char *kBadCerts[] = {
1783 "crypto/x509/test/pss_sha1_explicit.pem",
1784 "crypto/x509/test/pss_sha1_mgf1_syntax_error.pem",
1785 "crypto/x509/test/pss_sha1.pem",
1786 "crypto/x509/test/pss_sha224.pem",
1787 "crypto/x509/test/pss_sha256_mgf1_sha384.pem",
1788 "crypto/x509/test/pss_sha256_mgf1_syntax_error.pem",
1789 "crypto/x509/test/pss_sha256_salt_overflow.pem",
1790 "crypto/x509/test/pss_sha256_salt31.pem",
1791 "crypto/x509/test/pss_sha256_unknown_mgf.pem",
1792 "crypto/x509/test/pss_sha256_wrong_trailer.pem",
1793 };
1794 for (const char *path : kBadCerts) {
1795 SCOPED_TRACE(path);
1796 bssl::UniquePtr<X509> cert = CertFromPEM(GetTestData(path).c_str());
1797 ASSERT_TRUE(cert);
1798 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
1799 ASSERT_TRUE(pkey);
1800 EXPECT_FALSE(X509_verify(cert.get(), pkey.get()));
1801 }
David Benjamin93a69b42016-01-30 12:57:05 -05001802}
1803
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001804TEST(X509Test, TestPSSBadParameters) {
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001805 bssl::UniquePtr<X509> cert(CertFromPEM(kBadPSSCertPEM));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001806 ASSERT_TRUE(cert);
David Benjamin93a69b42016-01-30 12:57:05 -05001807
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001808 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001809 ASSERT_TRUE(pkey);
David Benjamin93a69b42016-01-30 12:57:05 -05001810
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001811 ASSERT_FALSE(X509_verify(cert.get(), pkey.get()));
David Benjamin93a69b42016-01-30 12:57:05 -05001812 ERR_clear_error();
David Benjamin93a69b42016-01-30 12:57:05 -05001813}
1814
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001815TEST(X509Test, TestEd25519) {
David Benjamind69d94e2017-03-29 16:08:50 -05001816 bssl::UniquePtr<X509> cert(CertFromPEM(kEd25519Cert));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001817 ASSERT_TRUE(cert);
David Benjamind69d94e2017-03-29 16:08:50 -05001818
1819 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001820 ASSERT_TRUE(pkey);
David Benjamind69d94e2017-03-29 16:08:50 -05001821
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001822 ASSERT_TRUE(X509_verify(cert.get(), pkey.get()));
David Benjamind69d94e2017-03-29 16:08:50 -05001823}
1824
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001825TEST(X509Test, TestEd25519BadParameters) {
David Benjamind69d94e2017-03-29 16:08:50 -05001826 bssl::UniquePtr<X509> cert(CertFromPEM(kEd25519CertNull));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001827 ASSERT_TRUE(cert);
David Benjamind69d94e2017-03-29 16:08:50 -05001828
1829 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001830 ASSERT_TRUE(pkey);
David Benjamind69d94e2017-03-29 16:08:50 -05001831
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001832 ASSERT_FALSE(X509_verify(cert.get(), pkey.get()));
1833
David Benjamind69d94e2017-03-29 16:08:50 -05001834 uint32_t err = ERR_get_error();
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001835 ASSERT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
1836 ASSERT_EQ(X509_R_INVALID_PARAMETER, ERR_GET_REASON(err));
David Benjamind69d94e2017-03-29 16:08:50 -05001837 ERR_clear_error();
David Benjamind69d94e2017-03-29 16:08:50 -05001838}
1839
Adam Langley1a751ee2020-10-30 16:29:02 -07001840TEST(X509Test, TestX25519) {
1841 bssl::UniquePtr<X509> cert(CertFromPEM(kX25519Cert));
1842 ASSERT_TRUE(cert);
1843
1844 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
1845 ASSERT_TRUE(pkey);
1846
1847 EXPECT_EQ(EVP_PKEY_id(pkey.get()), EVP_PKEY_X25519);
1848
1849 constexpr uint8_t kExpectedPublicValue[] = {
1850 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d,
1851 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38,
1852 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a,
1853 };
1854 uint8_t public_value[sizeof(kExpectedPublicValue)];
1855 size_t public_value_size = sizeof(public_value);
1856 ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), public_value,
1857 &public_value_size));
1858 EXPECT_EQ(Bytes(kExpectedPublicValue),
1859 Bytes(public_value, public_value_size));
1860}
1861
David Benjamin6dcce802020-11-02 18:16:14 -05001862static bssl::UniquePtr<X509> ReencodeCertificate(X509 *cert) {
1863 uint8_t *der = nullptr;
1864 int len = i2d_X509(cert, &der);
1865 bssl::UniquePtr<uint8_t> free_der(der);
1866 if (len <= 0) {
1867 return nullptr;
1868 }
1869
1870 const uint8_t *inp = der;
1871 return bssl::UniquePtr<X509>(d2i_X509(nullptr, &inp, len));
1872}
1873
David Benjamind8090a12022-10-01 12:40:47 -04001874static bssl::UniquePtr<X509_CRL> ReencodeCRL(X509_CRL *crl) {
1875 uint8_t *der = nullptr;
1876 int len = i2d_X509_CRL(crl, &der);
1877 bssl::UniquePtr<uint8_t> free_der(der);
1878 if (len <= 0) {
1879 return nullptr;
1880 }
1881
1882 const uint8_t *inp = der;
1883 return bssl::UniquePtr<X509_CRL>(d2i_X509_CRL(nullptr, &inp, len));
1884}
1885
1886static bssl::UniquePtr<X509_REQ> ReencodeCSR(X509_REQ *req) {
1887 uint8_t *der = nullptr;
1888 int len = i2d_X509_REQ(req, &der);
1889 bssl::UniquePtr<uint8_t> free_der(der);
1890 if (len <= 0) {
1891 return nullptr;
1892 }
1893
1894 const uint8_t *inp = der;
1895 return bssl::UniquePtr<X509_REQ>(d2i_X509_REQ(nullptr, &inp, len));
1896}
1897
David Benjamin93a69b42016-01-30 12:57:05 -05001898static bool SignatureRoundTrips(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
1899 // Make a certificate like signed with |md_ctx|'s settings.'
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001900 bssl::UniquePtr<X509> cert(CertFromPEM(kLeafPEM));
David Benjamin93a69b42016-01-30 12:57:05 -05001901 if (!cert || !X509_sign_ctx(cert.get(), md_ctx)) {
1902 return false;
1903 }
1904
1905 // Ensure that |pkey| may still be used to verify the resulting signature. All
1906 // settings in |md_ctx| must have been serialized appropriately.
David Benjamin6dcce802020-11-02 18:16:14 -05001907 if (!X509_verify(cert.get(), pkey)) {
1908 return false;
1909 }
1910
1911 // Re-encode the certificate. X509 objects contain a cached TBSCertificate
David Benjamin818c4aa2022-10-12 12:17:22 -04001912 // encoding and |X509_sign_ctx| should have dropped that cache.
David Benjamin6dcce802020-11-02 18:16:14 -05001913 bssl::UniquePtr<X509> copy = ReencodeCertificate(cert.get());
1914 return copy && X509_verify(copy.get(), pkey);
David Benjamin93a69b42016-01-30 12:57:05 -05001915}
1916
David Benjamin19670942017-05-31 19:07:31 -04001917TEST(X509Test, RSASign) {
Matt Braithwaited17d74d2016-08-17 20:10:28 -07001918 bssl::UniquePtr<EVP_PKEY> pkey(PrivateKeyFromPEM(kRSAKey));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001919 ASSERT_TRUE(pkey);
David Benjamin93a69b42016-01-30 12:57:05 -05001920 // Test PKCS#1 v1.5.
David Benjaminaac1e2d2016-12-06 22:35:41 -05001921 bssl::ScopedEVP_MD_CTX md_ctx;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02001922 ASSERT_TRUE(
1923 EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
1924 ASSERT_TRUE(SignatureRoundTrips(md_ctx.get(), pkey.get()));
David Benjamin93a69b42016-01-30 12:57:05 -05001925
David Benjamin17e530c2020-11-03 16:37:25 -05001926 // RSA-PSS with salt length matching hash length should work when passing in
1927 // -1 or the value explicitly.
1928 md_ctx.Reset();
David Benjamina6d321b2022-08-03 18:36:25 -04001929 EVP_PKEY_CTX *pkey_ctx;
David Benjamin17e530c2020-11-03 16:37:25 -05001930 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
1931 pkey.get()));
1932 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
1933 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1));
1934 ASSERT_TRUE(SignatureRoundTrips(md_ctx.get(), pkey.get()));
1935
1936 md_ctx.Reset();
1937 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
1938 pkey.get()));
1939 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
1940 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, 32));
1941 ASSERT_TRUE(SignatureRoundTrips(md_ctx.get(), pkey.get()));
David Benjamina6d321b2022-08-03 18:36:25 -04001942
1943 // RSA-PSS with SHA-1 is not supported.
1944 md_ctx.Reset();
1945 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha1(), NULL,
1946 pkey.get()));
1947 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
1948 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1));
1949 bssl::UniquePtr<X509> cert = CertFromPEM(kLeafPEM);
1950 ASSERT_TRUE(cert);
1951 EXPECT_FALSE(X509_sign_ctx(cert.get(), md_ctx.get()));
1952
1953 // RSA-PSS with mismatched hashes is not supported.
1954 md_ctx.Reset();
1955 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
1956 pkey.get()));
1957 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
1958 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1));
1959 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()));
1960 cert = CertFromPEM(kLeafPEM);
1961 ASSERT_TRUE(cert);
1962 EXPECT_FALSE(X509_sign_ctx(cert.get(), md_ctx.get()));
1963
1964 // RSA-PSS with the wrong salt length is not supported.
1965 md_ctx.Reset();
1966 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
1967 pkey.get()));
1968 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
1969 ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, 33));
1970 cert = CertFromPEM(kLeafPEM);
1971 ASSERT_TRUE(cert);
1972 EXPECT_FALSE(X509_sign_ctx(cert.get(), md_ctx.get()));
David Benjamin93a69b42016-01-30 12:57:05 -05001973}
1974
David Benjaminda96eeb2022-10-12 01:07:06 -04001975// Test the APIs for signing a certificate, particularly whether they correctly
1976// handle the TBSCertificate cache.
1977TEST(X509Test, SignCertificate) {
David Benjamin6dcce802020-11-02 18:16:14 -05001978 const int kSignatureNID = NID_sha384WithRSAEncryption;
1979 const EVP_MD *kSignatureHash = EVP_sha384();
1980
1981 bssl::UniquePtr<EVP_PKEY> pkey(PrivateKeyFromPEM(kRSAKey));
1982 ASSERT_TRUE(pkey);
1983 bssl::UniquePtr<X509_ALGOR> algor(X509_ALGOR_new());
1984 ASSERT_TRUE(algor);
1985 ASSERT_TRUE(X509_ALGOR_set0(algor.get(), OBJ_nid2obj(kSignatureNID),
1986 V_ASN1_NULL, nullptr));
1987
David Benjaminda96eeb2022-10-12 01:07:06 -04001988 // Test both signing with |X509_sign| and constructing a signature manually.
1989 for (bool sign_manual : {true, false}) {
1990 SCOPED_TRACE(sign_manual);
David Benjamin6dcce802020-11-02 18:16:14 -05001991
David Benjaminda96eeb2022-10-12 01:07:06 -04001992 // Test certificates made both from other certificates and |X509_new|, in
1993 // case there are bugs in filling in fields from different states. (Parsed
1994 // certificates contain a TBSCertificate cache, and |X509_new| initializes
1995 // fields based on complex ASN.1 template logic.)
1996 for (bool new_cert : {true, false}) {
1997 SCOPED_TRACE(new_cert);
David Benjamin6dcce802020-11-02 18:16:14 -05001998
David Benjaminda96eeb2022-10-12 01:07:06 -04001999 bssl::UniquePtr<X509> cert;
2000 if (new_cert) {
2001 cert.reset(X509_new());
2002 ASSERT_TRUE(cert);
2003 // Fill in some fields for the certificate arbitrarily.
2004 EXPECT_TRUE(X509_set_version(cert.get(), X509_VERSION_3));
2005 EXPECT_TRUE(
2006 ASN1_INTEGER_set_int64(X509_get_serialNumber(cert.get()), 1));
2007 EXPECT_TRUE(X509_gmtime_adj(X509_getm_notBefore(cert.get()), 0));
2008 EXPECT_TRUE(
2009 X509_gmtime_adj(X509_getm_notAfter(cert.get()), 60 * 60 * 24));
2010 X509_NAME *subject = X509_get_subject_name(cert.get());
2011 X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC,
2012 reinterpret_cast<const uint8_t *>("Test"),
2013 -1, -1, 0);
2014 EXPECT_TRUE(X509_set_issuer_name(cert.get(), subject));
2015 EXPECT_TRUE(X509_set_pubkey(cert.get(), pkey.get()));
2016 } else {
2017 // Extract fields from a parsed certificate.
2018 cert = CertFromPEM(kLeafPEM);
2019 ASSERT_TRUE(cert);
2020
2021 // We should test with a different algorithm from what is already in the
2022 // certificate.
2023 EXPECT_NE(kSignatureNID, X509_get_signature_nid(cert.get()));
2024 }
2025
2026 if (sign_manual) {
2027 // Fill in the signature algorithm.
2028 ASSERT_TRUE(X509_set1_signature_algo(cert.get(), algor.get()));
2029
2030 // Extract the TBSCertificiate.
2031 uint8_t *tbs_cert = nullptr;
2032 int tbs_cert_len = i2d_re_X509_tbs(cert.get(), &tbs_cert);
2033 bssl::UniquePtr<uint8_t> free_tbs_cert(tbs_cert);
2034 ASSERT_GT(tbs_cert_len, 0);
2035
2036 // Generate a signature externally and fill it in.
2037 bssl::ScopedEVP_MD_CTX md_ctx;
2038 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, kSignatureHash,
2039 nullptr, pkey.get()));
2040 size_t sig_len;
2041 ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), nullptr, &sig_len, tbs_cert,
2042 tbs_cert_len));
2043 std::vector<uint8_t> sig(sig_len);
2044 ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), sig.data(), &sig_len, tbs_cert,
2045 tbs_cert_len));
2046 sig.resize(sig_len);
2047 ASSERT_TRUE(
2048 X509_set1_signature_value(cert.get(), sig.data(), sig.size()));
2049 } else {
2050 ASSERT_TRUE(X509_sign(cert.get(), pkey.get(), EVP_sha384()));
2051 }
2052
2053 // Check the signature.
2054 EXPECT_TRUE(X509_verify(cert.get(), pkey.get()));
2055
2056 // Re-encode the certificate. X509 objects contain a cached TBSCertificate
David Benjaminca6fa612022-10-13 10:01:12 -04002057 // encoding and re-signing should have dropped that cache.
David Benjaminda96eeb2022-10-12 01:07:06 -04002058 bssl::UniquePtr<X509> copy = ReencodeCertificate(cert.get());
2059 ASSERT_TRUE(copy);
2060 EXPECT_TRUE(X509_verify(copy.get(), pkey.get()));
David Benjamin6dcce802020-11-02 18:16:14 -05002061 }
David Benjamin6dcce802020-11-02 18:16:14 -05002062 }
2063}
2064
David Benjaminda96eeb2022-10-12 01:07:06 -04002065// Test the APIs for signing a CRL, particularly whether they correctly handle
2066// the TBSCertList cache.
2067TEST(X509Test, SignCRL) {
David Benjamind8090a12022-10-01 12:40:47 -04002068 const int kSignatureNID = NID_sha384WithRSAEncryption;
2069 const EVP_MD *kSignatureHash = EVP_sha384();
2070
2071 bssl::UniquePtr<EVP_PKEY> pkey(PrivateKeyFromPEM(kRSAKey));
2072 ASSERT_TRUE(pkey);
2073 bssl::UniquePtr<X509_ALGOR> algor(X509_ALGOR_new());
2074 ASSERT_TRUE(algor);
2075 ASSERT_TRUE(X509_ALGOR_set0(algor.get(), OBJ_nid2obj(kSignatureNID),
2076 V_ASN1_NULL, nullptr));
2077
David Benjaminda96eeb2022-10-12 01:07:06 -04002078 // Test both signing with |X509_CRL_sign| and constructing a signature
2079 // manually.
2080 for (bool sign_manual : {true, false}) {
2081 SCOPED_TRACE(sign_manual);
David Benjamind8090a12022-10-01 12:40:47 -04002082
David Benjaminda96eeb2022-10-12 01:07:06 -04002083 // Test CRLs made both from other CRLs and |X509_CRL_new|, in case there are
2084 // bugs in filling in fields from different states. (Parsed CRLs contain a
2085 // TBSCertList cache, and |X509_CRL_new| initializes fields based on complex
2086 // ASN.1 template logic.)
2087 for (bool new_crl : {true, false}) {
2088 SCOPED_TRACE(new_crl);
David Benjamind8090a12022-10-01 12:40:47 -04002089
David Benjaminda96eeb2022-10-12 01:07:06 -04002090 bssl::UniquePtr<X509_CRL> crl;
2091 if (new_crl) {
2092 crl.reset(X509_CRL_new());
2093 ASSERT_TRUE(crl);
2094 // Fill in some fields for the certificate arbitrarily.
2095 ASSERT_TRUE(X509_CRL_set_version(crl.get(), X509_CRL_VERSION_2));
2096 bssl::UniquePtr<ASN1_TIME> last_update(ASN1_TIME_new());
2097 ASSERT_TRUE(last_update);
2098 ASSERT_TRUE(ASN1_TIME_set(last_update.get(), kReferenceTime));
2099 ASSERT_TRUE(X509_CRL_set1_lastUpdate(crl.get(), last_update.get()));
2100 bssl::UniquePtr<X509_NAME> issuer(X509_NAME_new());
2101 ASSERT_TRUE(issuer);
2102 ASSERT_TRUE(X509_NAME_add_entry_by_txt(
2103 issuer.get(), "CN", MBSTRING_ASC,
2104 reinterpret_cast<const uint8_t *>("Test"), -1, -1, 0));
2105 EXPECT_TRUE(X509_CRL_set_issuer_name(crl.get(), issuer.get()));
2106 } else {
2107 // Extract fields from a parsed CRL.
2108 crl = CRLFromPEM(kBasicCRL);
2109 ASSERT_TRUE(crl);
2110
2111 // We should test with a different algorithm from what is already in the
2112 // CRL.
2113 EXPECT_NE(kSignatureNID, X509_CRL_get_signature_nid(crl.get()));
2114 }
2115
2116 if (sign_manual) {
2117 // Fill in the signature algorithm.
2118 ASSERT_TRUE(X509_CRL_set1_signature_algo(crl.get(), algor.get()));
2119
2120 // Extract the TBSCertList.
2121 uint8_t *tbs = nullptr;
2122 int tbs_len = i2d_re_X509_CRL_tbs(crl.get(), &tbs);
2123 bssl::UniquePtr<uint8_t> free_tbs(tbs);
2124 ASSERT_GT(tbs_len, 0);
2125
2126 // Generate a signature externally and fill it in.
2127 bssl::ScopedEVP_MD_CTX md_ctx;
2128 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, kSignatureHash,
2129 nullptr, pkey.get()));
2130 size_t sig_len;
2131 ASSERT_TRUE(
2132 EVP_DigestSign(md_ctx.get(), nullptr, &sig_len, tbs, tbs_len));
2133 std::vector<uint8_t> sig(sig_len);
2134 ASSERT_TRUE(
2135 EVP_DigestSign(md_ctx.get(), sig.data(), &sig_len, tbs, tbs_len));
2136 sig.resize(sig_len);
2137 ASSERT_TRUE(
2138 X509_CRL_set1_signature_value(crl.get(), sig.data(), sig.size()));
2139 } else {
2140 ASSERT_TRUE(X509_CRL_sign(crl.get(), pkey.get(), EVP_sha384()));
2141 }
2142
2143 // Check the signature.
2144 EXPECT_TRUE(X509_CRL_verify(crl.get(), pkey.get()));
2145
2146 // Re-encode the CRL. X509_CRL objects contain a cached TBSCertList
David Benjaminca6fa612022-10-13 10:01:12 -04002147 // encoding and re-signing should have dropped that cache.
David Benjaminda96eeb2022-10-12 01:07:06 -04002148 bssl::UniquePtr<X509_CRL> copy = ReencodeCRL(crl.get());
2149 ASSERT_TRUE(copy);
2150 EXPECT_TRUE(X509_CRL_verify(copy.get(), pkey.get()));
David Benjamind8090a12022-10-01 12:40:47 -04002151 }
David Benjamind8090a12022-10-01 12:40:47 -04002152 }
2153}
2154
2155static const char kTestCSR[] = R"(
2156-----BEGIN CERTIFICATE REQUEST-----
2157MIICVDCCATwCAQAwDzENMAsGA1UEAwwEVGVzdDCCASIwDQYJKoZIhvcNAQEBBQAD
2158ggEPADCCAQoCggEBAK+UkwcNJfRhg5MzIQzxDdrqF9a76jNoK/BwCflKYFX7QEqf
2159rsLkI0J+m60fUD0v50LnKwbGoMFKZ1R/3cBNXLcdXb7ZP/ZJ7A7QwUrL+W9n3sov
2160U8/HSU3rHbg+V5L6egSZYuhDHoXKi33HDOL4DVUzMoU1ykmP4QwF1wUXHLqvqjbU
2161teQBoJWO53/XOGQu8bX04muCFnHZWT2Ubqol70JwPU2PqDU1EBlgUFO79NEmflev
2162b++H8tu42UCDUZXD9k5weftjneO4cud3IsUX6mDsyf7k1e2mxsS4TSZsJcG0iLBX
2163HSr1udXazQsjlAKjJkoI3cWshF6LGRWssAtbGiUCAwEAAaAAMA0GCSqGSIb3DQEB
2164CwUAA4IBAQAniYZL+amXu+wED+AwBZz+zPuxY16bveF27/gxcs/jq6hVpEQvMxfO
2165jfAGeDRtAU7DMxdJPjvWwwNe2JlTMSRoVDMYaiKqB5yxIYa2cjQvp7swSxuFJwbG
2166T8h7/d7yqem6NYYzgYsNOE5QJyNu/PsIEdvzrysfDAnREiT2ituOcVpiqUZq3DTj
2167NaTd1GNG3j4E87ZUmayUJD5nH91UNzKvJbpfo+bLyfy73x4QeU0SRitsZmbSBTAi
2168s9+zmCErxzMlAdJHGzxPkXmtvBnUzGRIsAD5h/DjYNUmQJkB60yplt84ZgThhx54
2169rZGEJG3+X9OuhczVKGJyg+3gU7oDbecc
2170-----END CERTIFICATE REQUEST-----
2171)";
2172
David Benjaminda96eeb2022-10-12 01:07:06 -04002173// Test the APIs for signing a CSR, particularly whether they correctly handle
2174// the CertificationRequestInfo cache.
2175TEST(X509Test, SignCSR) {
David Benjamind8090a12022-10-01 12:40:47 -04002176 const int kSignatureNID = NID_sha384WithRSAEncryption;
2177 const EVP_MD *kSignatureHash = EVP_sha384();
2178
2179 bssl::UniquePtr<EVP_PKEY> pkey(PrivateKeyFromPEM(kRSAKey));
2180 ASSERT_TRUE(pkey);
2181 bssl::UniquePtr<X509_ALGOR> algor(X509_ALGOR_new());
2182 ASSERT_TRUE(algor);
2183 ASSERT_TRUE(X509_ALGOR_set0(algor.get(), OBJ_nid2obj(kSignatureNID),
2184 V_ASN1_NULL, nullptr));
2185
David Benjaminda96eeb2022-10-12 01:07:06 -04002186 // Test both signing with |X509_REQ_sign| and constructing a signature
2187 // manually.
2188 for (bool sign_manual : {true, false}) {
2189 SCOPED_TRACE(sign_manual);
David Benjamind8090a12022-10-01 12:40:47 -04002190
David Benjaminda96eeb2022-10-12 01:07:06 -04002191 // Test CSRs made both from other CSRs and |X509_REQ_new|, in case there are
2192 // bugs in filling in fields from different states. (Parsed CSRs contain a
2193 // CertificationRequestInfo cache, and |X509_REQ_new| initializes fields
2194 // based on complex ASN.1 template logic.)
2195 for (bool new_csr : {true, false}) {
2196 SCOPED_TRACE(new_csr);
2197
2198 bssl::UniquePtr<X509_REQ> csr;
2199 if (new_csr) {
2200 csr.reset(X509_REQ_new());
2201 ASSERT_TRUE(csr);
2202 bssl::UniquePtr<X509_NAME> subject(X509_NAME_new());
2203 ASSERT_TRUE(subject);
2204 ASSERT_TRUE(X509_NAME_add_entry_by_txt(
2205 subject.get(), "CN", MBSTRING_ASC,
2206 reinterpret_cast<const uint8_t *>("New CSR"), -1, -1, 0));
2207 EXPECT_TRUE(X509_REQ_set_subject_name(csr.get(), subject.get()));
2208 } else {
2209 // Extract fields from a parsed CSR.
2210 csr = CSRFromPEM(kTestCSR);
2211 ASSERT_TRUE(csr);
2212 }
2213
2214 // Override the public key from the CSR unconditionally. Unlike
2215 // certificates and CRLs, CSRs do not contain a signed copy of the
2216 // signature algorithm, so we use a different field to confirm
2217 // |i2d_re_X509_REQ_tbs| clears the cache as expected.
2218 EXPECT_TRUE(X509_REQ_set_pubkey(csr.get(), pkey.get()));
2219
2220 if (sign_manual) {
David Benjaminca6fa612022-10-13 10:01:12 -04002221 // Fill in the signature algorithm.
2222 ASSERT_TRUE(X509_REQ_set1_signature_algo(csr.get(), algor.get()));
David Benjaminda96eeb2022-10-12 01:07:06 -04002223
David Benjaminca6fa612022-10-13 10:01:12 -04002224 // Extract the CertificationRequestInfo.
2225 uint8_t *tbs = nullptr;
2226 int tbs_len = i2d_re_X509_REQ_tbs(csr.get(), &tbs);
2227 bssl::UniquePtr<uint8_t> free_tbs(tbs);
2228 ASSERT_GT(tbs_len, 0);
David Benjaminda96eeb2022-10-12 01:07:06 -04002229
David Benjaminca6fa612022-10-13 10:01:12 -04002230 // Generate a signature externally and fill it in.
2231 bssl::ScopedEVP_MD_CTX md_ctx;
2232 ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, kSignatureHash,
2233 nullptr, pkey.get()));
2234 size_t sig_len;
2235 ASSERT_TRUE(
2236 EVP_DigestSign(md_ctx.get(), nullptr, &sig_len, tbs, tbs_len));
2237 std::vector<uint8_t> sig(sig_len);
2238 ASSERT_TRUE(
2239 EVP_DigestSign(md_ctx.get(), sig.data(), &sig_len, tbs, tbs_len));
2240 sig.resize(sig_len);
2241 ASSERT_TRUE(
2242 X509_REQ_set1_signature_value(csr.get(), sig.data(), sig.size()));
David Benjaminda96eeb2022-10-12 01:07:06 -04002243 } else {
2244 ASSERT_TRUE(X509_REQ_sign(csr.get(), pkey.get(), EVP_sha384()));
2245 }
2246
2247 // Check the signature.
2248 EXPECT_TRUE(X509_REQ_verify(csr.get(), pkey.get()));
2249
2250 // Re-encode the CSR. X509_REQ objects contain a cached
David Benjaminca6fa612022-10-13 10:01:12 -04002251 // CertificationRequestInfo encoding and re-signing should have dropped
2252 // that cache.
David Benjaminda96eeb2022-10-12 01:07:06 -04002253 bssl::UniquePtr<X509_REQ> copy = ReencodeCSR(csr.get());
2254 ASSERT_TRUE(copy);
2255 EXPECT_TRUE(X509_REQ_verify(copy.get(), pkey.get()));
2256
2257 // Check the signature was over the new public key.
2258 bssl::UniquePtr<EVP_PKEY> copy_pubkey(X509_REQ_get_pubkey(copy.get()));
2259 ASSERT_TRUE(copy_pubkey);
2260 EXPECT_EQ(1, EVP_PKEY_cmp(pkey.get(), copy_pubkey.get()));
David Benjamind8090a12022-10-01 12:40:47 -04002261 }
David Benjamind8090a12022-10-01 12:40:47 -04002262 }
2263}
2264
David Benjamin19670942017-05-31 19:07:31 -04002265TEST(X509Test, Ed25519Sign) {
2266 uint8_t pub_bytes[32], priv_bytes[64];
2267 ED25519_keypair(pub_bytes, priv_bytes);
2268
David Benjaminb3239c62019-04-27 13:44:22 -05002269 bssl::UniquePtr<EVP_PKEY> pub(
2270 EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, nullptr, pub_bytes, 32));
David Benjamin19670942017-05-31 19:07:31 -04002271 ASSERT_TRUE(pub);
David Benjaminb3239c62019-04-27 13:44:22 -05002272 bssl::UniquePtr<EVP_PKEY> priv(
2273 EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, nullptr, priv_bytes, 32));
David Benjamin19670942017-05-31 19:07:31 -04002274 ASSERT_TRUE(priv);
2275
2276 bssl::ScopedEVP_MD_CTX md_ctx;
2277 ASSERT_TRUE(
2278 EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, priv.get()));
2279 ASSERT_TRUE(SignatureRoundTrips(md_ctx.get(), pub.get()));
2280}
2281
Adam Langley48983312016-10-28 11:42:45 -07002282static bool PEMToDER(bssl::UniquePtr<uint8_t> *out, size_t *out_len,
2283 const char *pem) {
2284 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
2285 if (!bio) {
2286 return false;
2287 }
2288
2289 char *name, *header;
2290 uint8_t *data;
2291 long data_len;
2292 if (!PEM_read_bio(bio.get(), &name, &header, &data, &data_len)) {
2293 fprintf(stderr, "failed to read PEM data.\n");
2294 return false;
2295 }
2296 OPENSSL_free(name);
2297 OPENSSL_free(header);
2298
2299 out->reset(data);
2300 *out_len = data_len;
2301
2302 return true;
2303}
2304
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002305TEST(X509Test, TestFromBuffer) {
Adam Langley48983312016-10-28 11:42:45 -07002306 size_t data_len;
2307 bssl::UniquePtr<uint8_t> data;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002308 ASSERT_TRUE(PEMToDER(&data, &data_len, kRootCAPEM));
Adam Langley48983312016-10-28 11:42:45 -07002309
2310 bssl::UniquePtr<CRYPTO_BUFFER> buf(
2311 CRYPTO_BUFFER_new(data.get(), data_len, nullptr));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002312 ASSERT_TRUE(buf);
Adam Langleyd50f1c82016-11-07 14:06:19 -08002313 bssl::UniquePtr<X509> root(X509_parse_from_buffer(buf.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002314 ASSERT_TRUE(root);
Adam Langley48983312016-10-28 11:42:45 -07002315
2316 const uint8_t *enc_pointer = root->cert_info->enc.enc;
2317 const uint8_t *buf_pointer = CRYPTO_BUFFER_data(buf.get());
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002318 ASSERT_GE(enc_pointer, buf_pointer);
2319 ASSERT_LT(enc_pointer, buf_pointer + CRYPTO_BUFFER_len(buf.get()));
Adam Langley48983312016-10-28 11:42:45 -07002320 buf.reset();
2321
2322 /* This ensures the X509 took a reference to |buf|, otherwise this will be a
2323 * reference to free memory and ASAN should notice. */
David Benjamind9f49972017-12-21 23:11:23 -05002324 ASSERT_EQ(0x30, enc_pointer[0]);
Adam Langley48983312016-10-28 11:42:45 -07002325}
2326
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002327TEST(X509Test, TestFromBufferWithTrailingData) {
Adam Langley48983312016-10-28 11:42:45 -07002328 size_t data_len;
2329 bssl::UniquePtr<uint8_t> data;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002330 ASSERT_TRUE(PEMToDER(&data, &data_len, kRootCAPEM));
Adam Langley48983312016-10-28 11:42:45 -07002331
2332 std::unique_ptr<uint8_t[]> trailing_data(new uint8_t[data_len + 1]);
David Benjamin17cf2cb2016-12-13 01:07:13 -05002333 OPENSSL_memcpy(trailing_data.get(), data.get(), data_len);
Adam Langley48983312016-10-28 11:42:45 -07002334
2335 bssl::UniquePtr<CRYPTO_BUFFER> buf_trailing_data(
2336 CRYPTO_BUFFER_new(trailing_data.get(), data_len + 1, nullptr));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002337 ASSERT_TRUE(buf_trailing_data);
Adam Langley48983312016-10-28 11:42:45 -07002338
2339 bssl::UniquePtr<X509> root_trailing_data(
Adam Langleyd50f1c82016-11-07 14:06:19 -08002340 X509_parse_from_buffer(buf_trailing_data.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002341 ASSERT_FALSE(root_trailing_data);
Adam Langley48983312016-10-28 11:42:45 -07002342}
2343
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002344TEST(X509Test, TestFromBufferModified) {
Adam Langley48983312016-10-28 11:42:45 -07002345 size_t data_len;
2346 bssl::UniquePtr<uint8_t> data;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002347 ASSERT_TRUE(PEMToDER(&data, &data_len, kRootCAPEM));
Adam Langley48983312016-10-28 11:42:45 -07002348
2349 bssl::UniquePtr<CRYPTO_BUFFER> buf(
2350 CRYPTO_BUFFER_new(data.get(), data_len, nullptr));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002351 ASSERT_TRUE(buf);
Adam Langley48983312016-10-28 11:42:45 -07002352
Adam Langleyd50f1c82016-11-07 14:06:19 -08002353 bssl::UniquePtr<X509> root(X509_parse_from_buffer(buf.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002354 ASSERT_TRUE(root);
Adam Langley48983312016-10-28 11:42:45 -07002355
2356 bssl::UniquePtr<ASN1_INTEGER> fourty_two(ASN1_INTEGER_new());
David Benjamincab31f62022-09-23 15:22:39 -04002357 ASN1_INTEGER_set_int64(fourty_two.get(), 42);
Adam Langley48983312016-10-28 11:42:45 -07002358 X509_set_serialNumber(root.get(), fourty_two.get());
2359
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002360 ASSERT_EQ(static_cast<long>(data_len), i2d_X509(root.get(), nullptr));
Adam Langley48983312016-10-28 11:42:45 -07002361
David Benjaminfcec3912021-04-20 14:58:30 -04002362 // Re-encode the TBSCertificate.
2363 i2d_re_X509_tbs(root.get(), nullptr);
Adam Langley48983312016-10-28 11:42:45 -07002364
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002365 ASSERT_NE(static_cast<long>(data_len), i2d_X509(root.get(), nullptr));
Adam Langley48983312016-10-28 11:42:45 -07002366}
2367
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002368TEST(X509Test, TestFromBufferReused) {
Adam Langley48983312016-10-28 11:42:45 -07002369 size_t data_len;
2370 bssl::UniquePtr<uint8_t> data;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002371 ASSERT_TRUE(PEMToDER(&data, &data_len, kRootCAPEM));
Adam Langley48983312016-10-28 11:42:45 -07002372
2373 bssl::UniquePtr<CRYPTO_BUFFER> buf(
2374 CRYPTO_BUFFER_new(data.get(), data_len, nullptr));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002375 ASSERT_TRUE(buf);
Adam Langley48983312016-10-28 11:42:45 -07002376
Adam Langleyd50f1c82016-11-07 14:06:19 -08002377 bssl::UniquePtr<X509> root(X509_parse_from_buffer(buf.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002378 ASSERT_TRUE(root);
Adam Langley48983312016-10-28 11:42:45 -07002379
2380 size_t data2_len;
2381 bssl::UniquePtr<uint8_t> data2;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002382 ASSERT_TRUE(PEMToDER(&data2, &data2_len, kLeafPEM));
Adam Langley48983312016-10-28 11:42:45 -07002383
2384 X509 *x509p = root.get();
2385 const uint8_t *inp = data2.get();
2386 X509 *ret = d2i_X509(&x509p, &inp, data2_len);
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002387 ASSERT_EQ(root.get(), ret);
2388 ASSERT_EQ(nullptr, root->buf);
Adam Langley48983312016-10-28 11:42:45 -07002389
2390 // Free |data2| and ensure that |root| took its own copy. Otherwise the
2391 // following will trigger a use-after-free.
2392 data2.reset();
2393
Adam Langleyd50f1c82016-11-07 14:06:19 -08002394 uint8_t *i2d = nullptr;
2395 int i2d_len = i2d_X509(root.get(), &i2d);
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002396 ASSERT_GE(i2d_len, 0);
Adam Langleyd50f1c82016-11-07 14:06:19 -08002397 bssl::UniquePtr<uint8_t> i2d_storage(i2d);
Adam Langley48983312016-10-28 11:42:45 -07002398
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002399 ASSERT_TRUE(PEMToDER(&data2, &data2_len, kLeafPEM));
Adam Langley48983312016-10-28 11:42:45 -07002400
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002401 ASSERT_EQ(static_cast<long>(data2_len), i2d_len);
2402 ASSERT_EQ(0, OPENSSL_memcmp(data2.get(), i2d, i2d_len));
2403 ASSERT_EQ(nullptr, root->buf);
Adam Langley48983312016-10-28 11:42:45 -07002404}
2405
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002406TEST(X509Test, TestFailedParseFromBuffer) {
Adam Langleyc8006be2016-12-07 16:45:24 -08002407 static const uint8_t kNonsense[] = {1, 2, 3, 4, 5};
2408
2409 bssl::UniquePtr<CRYPTO_BUFFER> buf(
2410 CRYPTO_BUFFER_new(kNonsense, sizeof(kNonsense), nullptr));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002411 ASSERT_TRUE(buf);
Adam Langleyc8006be2016-12-07 16:45:24 -08002412
2413 bssl::UniquePtr<X509> cert(X509_parse_from_buffer(buf.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002414 ASSERT_FALSE(cert);
Adam Langleyc8006be2016-12-07 16:45:24 -08002415 ERR_clear_error();
2416
2417 // Test a buffer with trailing data.
2418 size_t data_len;
2419 bssl::UniquePtr<uint8_t> data;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002420 ASSERT_TRUE(PEMToDER(&data, &data_len, kRootCAPEM));
Adam Langleyc8006be2016-12-07 16:45:24 -08002421
2422 std::unique_ptr<uint8_t[]> data_with_trailing_byte(new uint8_t[data_len + 1]);
David Benjamin17cf2cb2016-12-13 01:07:13 -05002423 OPENSSL_memcpy(data_with_trailing_byte.get(), data.get(), data_len);
Adam Langleyc8006be2016-12-07 16:45:24 -08002424 data_with_trailing_byte[data_len] = 0;
2425
2426 bssl::UniquePtr<CRYPTO_BUFFER> buf_with_trailing_byte(
2427 CRYPTO_BUFFER_new(data_with_trailing_byte.get(), data_len + 1, nullptr));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002428 ASSERT_TRUE(buf_with_trailing_byte);
Adam Langleyc8006be2016-12-07 16:45:24 -08002429
2430 bssl::UniquePtr<X509> root(
2431 X509_parse_from_buffer(buf_with_trailing_byte.get()));
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002432 ASSERT_FALSE(root);
Adam Langleyc8006be2016-12-07 16:45:24 -08002433 ERR_clear_error();
Adam Langleyc8006be2016-12-07 16:45:24 -08002434}
2435
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002436TEST(X509Test, TestPrintUTCTIME) {
Matthew Braithwaitee2c083d2017-01-06 13:35:32 -08002437 static const struct {
2438 const char *val, *want;
2439 } asn1_utctime_tests[] = {
2440 {"", "Bad time value"},
2441
2442 // Correct RFC 5280 form. Test years < 2000 and > 2000.
2443 {"090303125425Z", "Mar 3 12:54:25 2009 GMT"},
2444 {"900303125425Z", "Mar 3 12:54:25 1990 GMT"},
2445 {"000303125425Z", "Mar 3 12:54:25 2000 GMT"},
2446
2447 // Correct form, bad values.
2448 {"000000000000Z", "Bad time value"},
2449 {"999999999999Z", "Bad time value"},
2450
David Benjaminfdeb4aa2022-06-22 14:18:20 -04002451 // Missing components.
2452 {"090303125425", "Bad time value"},
2453 {"9003031254", "Bad time value"},
2454 {"9003031254Z", "Bad time value"},
Matthew Braithwaitee2c083d2017-01-06 13:35:32 -08002455
2456 // GENERALIZEDTIME confused for UTCTIME.
2457 {"20090303125425Z", "Bad time value"},
2458
2459 // Legal ASN.1, but not legal RFC 5280.
2460 {"9003031254+0800", "Bad time value"},
2461 {"9003031254-0800", "Bad time value"},
2462
2463 // Trailing garbage.
2464 {"9003031254Z ", "Bad time value"},
2465 };
2466
2467 for (auto t : asn1_utctime_tests) {
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002468 SCOPED_TRACE(t.val);
Matthew Braithwaitee2c083d2017-01-06 13:35:32 -08002469 bssl::UniquePtr<ASN1_UTCTIME> tm(ASN1_UTCTIME_new());
2470 bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
2471
2472 // Use this instead of ASN1_UTCTIME_set() because some callers get
2473 // type-confused and pass ASN1_GENERALIZEDTIME to ASN1_UTCTIME_print().
2474 // ASN1_UTCTIME_set_string() is stricter, and would reject the inputs in
2475 // question.
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002476 ASSERT_TRUE(ASN1_STRING_set(tm.get(), t.val, strlen(t.val)));
Matthew Braithwaitee2c083d2017-01-06 13:35:32 -08002477 const int ok = ASN1_UTCTIME_print(bio.get(), tm.get());
2478
2479 const uint8_t *contents;
2480 size_t len;
Kári Tristan Helgason54581cc2017-06-07 12:28:27 +02002481 ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
2482 EXPECT_EQ(ok, (strcmp(t.want, "Bad time value") != 0) ? 1 : 0);
2483 EXPECT_EQ(t.want,
2484 std::string(reinterpret_cast<const char *>(contents), len));
Matthew Braithwaitee2c083d2017-01-06 13:35:32 -08002485 }
Adam Langley3a39b062016-01-14 14:08:58 -08002486}
David Benjamin56aaf162017-11-24 12:36:51 -05002487
2488TEST(X509Test, PrettyPrintIntegers) {
2489 static const char *kTests[] = {
2490 // Small numbers are pretty-printed in decimal.
2491 "0",
2492 "-1",
2493 "1",
2494 "42",
2495 "-42",
2496 "256",
2497 "-256",
2498 // Large numbers are pretty-printed in hex to avoid taking quadratic time.
2499 "0x0123456789",
2500 "-0x0123456789",
2501 };
2502 for (const char *in : kTests) {
2503 SCOPED_TRACE(in);
2504 BIGNUM *bn = nullptr;
2505 ASSERT_TRUE(BN_asc2bn(&bn, in));
2506 bssl::UniquePtr<BIGNUM> free_bn(bn);
2507
2508 {
2509 bssl::UniquePtr<ASN1_INTEGER> asn1(BN_to_ASN1_INTEGER(bn, nullptr));
2510 ASSERT_TRUE(asn1);
2511 bssl::UniquePtr<char> out(i2s_ASN1_INTEGER(nullptr, asn1.get()));
2512 ASSERT_TRUE(out.get());
2513 EXPECT_STREQ(in, out.get());
2514 }
2515
2516 {
2517 bssl::UniquePtr<ASN1_ENUMERATED> asn1(BN_to_ASN1_ENUMERATED(bn, nullptr));
2518 ASSERT_TRUE(asn1);
2519 bssl::UniquePtr<char> out(i2s_ASN1_ENUMERATED(nullptr, asn1.get()));
2520 ASSERT_TRUE(out.get());
2521 EXPECT_STREQ(in, out.get());
2522 }
2523 }
2524}
Steven Valdezdd444b12018-05-03 13:15:12 -04002525
2526TEST(X509Test, X509NameSet) {
2527 bssl::UniquePtr<X509_NAME> name(X509_NAME_new());
2528 EXPECT_TRUE(X509_NAME_add_entry_by_txt(
2529 name.get(), "C", MBSTRING_ASC, reinterpret_cast<const uint8_t *>("US"),
2530 -1, -1, 0));
2531 EXPECT_EQ(X509_NAME_entry_count(name.get()), 1);
2532 EXPECT_TRUE(X509_NAME_add_entry_by_txt(
2533 name.get(), "C", MBSTRING_ASC, reinterpret_cast<const uint8_t *>("CA"),
2534 -1, -1, 0));
2535 EXPECT_EQ(X509_NAME_entry_count(name.get()), 2);
2536 EXPECT_TRUE(X509_NAME_add_entry_by_txt(
2537 name.get(), "C", MBSTRING_ASC, reinterpret_cast<const uint8_t *>("UK"),
2538 -1, -1, 0));
2539 EXPECT_EQ(X509_NAME_entry_count(name.get()), 3);
2540 EXPECT_TRUE(X509_NAME_add_entry_by_txt(
2541 name.get(), "C", MBSTRING_ASC, reinterpret_cast<const uint8_t *>("JP"),
2542 -1, 1, 0));
2543 EXPECT_EQ(X509_NAME_entry_count(name.get()), 4);
2544
2545 // Check that the correct entries get incremented when inserting new entry.
2546 EXPECT_EQ(X509_NAME_ENTRY_set(X509_NAME_get_entry(name.get(), 1)), 1);
2547 EXPECT_EQ(X509_NAME_ENTRY_set(X509_NAME_get_entry(name.get(), 2)), 2);
2548}
David Benjaminae153bb2018-05-10 16:23:03 -04002549
David Benjamin3a5c4ff2023-01-04 18:19:51 -08002550// Tests that |X509_NAME_hash| and |X509_NAME_hash_old|'s values never change.
2551// These functions figure into |X509_LOOKUP_hash_dir|'s on-disk format, so they
2552// must remain stable. In particular, if we ever remove name canonicalization,
2553// we'll need to preserve it for |X509_NAME_hash|.
2554TEST(X509Test, NameHash) {
2555 struct {
2556 std::vector<uint8_t> name_der;
2557 unsigned long hash;
2558 unsigned long hash_old;
2559 } kTests[] = {
2560 // SEQUENCE {
2561 // SET {
2562 // SEQUENCE {
2563 // # commonName
2564 // OBJECT_IDENTIFIER { 2.5.4.3 }
2565 // UTF8String { "Test Name" }
2566 // }
2567 // }
2568 // }
2569 {{0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03,
2570 0x0c, 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x65},
2571 0xc90fba01,
2572 0x8c0d4fea},
2573
2574 // This name canonicalizes to the same value, with OpenSSL's algorithm, as
2575 // the above input, so |hash| matches. |hash_old| doesn't use
2576 // canonicalization and does not match.
2577 //
2578 // SEQUENCE {
2579 // SET {
2580 // SEQUENCE {
2581 // # commonName
2582 // OBJECT_IDENTIFIER { 2.5.4.3 }
2583 // BMPString {
2584 // u"\x09\n\x0b\x0c\x0d tEST\x09\n\x0b\x0c\x0d "
2585 // u"\x09\n\x0b\x0c\x0d nAME\x09\n\x0b\x0c\x0d "
2586 // }
2587 // }
2588 // }
2589 // }
2590 {{0x30, 0x4b, 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55, 0x04, 0x03,
2591 0x1e, 0x40, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00,
2592 0x0d, 0x00, 0x20, 0x00, 0x74, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54,
2593 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00,
2594 0x20, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d,
2595 0x00, 0x20, 0x00, 0x6e, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x45, 0x00,
2596 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x20},
2597 0xc90fba01,
2598 0xbe2dd8c8},
2599 };
2600 for (const auto &t : kTests) {
2601 SCOPED_TRACE(Bytes(t.name_der));
2602 const uint8_t *der = t.name_der.data();
2603 bssl::UniquePtr<X509_NAME> name(
2604 d2i_X509_NAME(nullptr, &der, t.name_der.size()));
2605 ASSERT_TRUE(name);
2606 EXPECT_EQ(t.hash, X509_NAME_hash(name.get()));
2607 EXPECT_EQ(t.hash_old, X509_NAME_hash_old(name.get()));
2608 }
2609}
2610
Adam Langley0224a322018-07-31 16:19:17 -07002611TEST(X509Test, NoBasicConstraintsCertSign) {
2612 bssl::UniquePtr<X509> root(CertFromPEM(kSANTypesRoot));
2613 bssl::UniquePtr<X509> intermediate(
2614 CertFromPEM(kNoBasicConstraintsCertSignIntermediate));
2615 bssl::UniquePtr<X509> leaf(CertFromPEM(kNoBasicConstraintsCertSignLeaf));
2616
2617 ASSERT_TRUE(root);
2618 ASSERT_TRUE(intermediate);
2619 ASSERT_TRUE(leaf);
2620
2621 // The intermediate has keyUsage certSign, but is not marked as a CA in the
Adam Langley8bd1d072018-07-31 16:42:31 -07002622 // basicConstraints.
2623 EXPECT_EQ(X509_V_ERR_INVALID_CA,
Adam Langley0224a322018-07-31 16:19:17 -07002624 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0));
Adam Langley0224a322018-07-31 16:19:17 -07002625}
2626
2627TEST(X509Test, NoBasicConstraintsNetscapeCA) {
2628 bssl::UniquePtr<X509> root(CertFromPEM(kSANTypesRoot));
2629 bssl::UniquePtr<X509> intermediate(
2630 CertFromPEM(kNoBasicConstraintsNetscapeCAIntermediate));
2631 bssl::UniquePtr<X509> leaf(CertFromPEM(kNoBasicConstraintsNetscapeCALeaf));
2632
2633 ASSERT_TRUE(root);
2634 ASSERT_TRUE(intermediate);
2635 ASSERT_TRUE(leaf);
2636
2637 // The intermediate has a Netscape certificate type of "SSL CA", but is not
Adam Langley8bd1d072018-07-31 16:42:31 -07002638 // marked as a CA in the basicConstraints.
2639 EXPECT_EQ(X509_V_ERR_INVALID_CA,
Adam Langley0224a322018-07-31 16:19:17 -07002640 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0));
Adam Langley0224a322018-07-31 16:19:17 -07002641}
David Benjamin371305f2018-09-18 13:14:53 -07002642
2643TEST(X509Test, MismatchAlgorithms) {
2644 bssl::UniquePtr<X509> cert(CertFromPEM(kSelfSignedMismatchAlgorithms));
2645 ASSERT_TRUE(cert);
2646
2647 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
2648 ASSERT_TRUE(pkey);
2649
2650 EXPECT_FALSE(X509_verify(cert.get(), pkey.get()));
2651 uint32_t err = ERR_get_error();
2652 EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
2653 EXPECT_EQ(X509_R_SIGNATURE_ALGORITHM_MISMATCH, ERR_GET_REASON(err));
2654}
David Benjamine7692f52018-09-23 00:06:31 -05002655
2656TEST(X509Test, PEMX509Info) {
2657 std::string cert = kRootCAPEM;
2658 auto cert_obj = CertFromPEM(kRootCAPEM);
2659 ASSERT_TRUE(cert_obj);
2660
2661 std::string rsa = kRSAKey;
2662 auto rsa_obj = PrivateKeyFromPEM(kRSAKey);
2663 ASSERT_TRUE(rsa_obj);
2664
2665 std::string crl = kBasicCRL;
2666 auto crl_obj = CRLFromPEM(kBasicCRL);
2667 ASSERT_TRUE(crl_obj);
2668
2669 std::string unknown =
2670 "-----BEGIN UNKNOWN-----\n"
2671 "AAAA\n"
2672 "-----END UNKNOWN-----\n";
2673
David Benjamin792c1dc2018-09-23 00:39:53 -05002674 std::string invalid =
2675 "-----BEGIN CERTIFICATE-----\n"
2676 "AAAA\n"
2677 "-----END CERTIFICATE-----\n";
2678
David Benjamine7692f52018-09-23 00:06:31 -05002679 // Each X509_INFO contains at most one certificate, CRL, etc. The format
2680 // creates a new X509_INFO when a repeated type is seen.
2681 std::string pem =
2682 // The first few entries have one of everything in different orders.
2683 cert + rsa + crl +
2684 rsa + crl + cert +
2685 // Unknown types are ignored.
2686 crl + unknown + cert + rsa +
2687 // Seeing a new certificate starts a new entry, so now we have a bunch of
2688 // certificate-only entries.
2689 cert + cert + cert +
2690 // The key folds into the certificate's entry.
2691 cert + rsa +
2692 // Doubled keys also start new entries.
2693 rsa + rsa + rsa + rsa + crl +
2694 // As do CRLs.
2695 crl + crl;
2696
2697 const struct ExpectedInfo {
2698 const X509 *cert;
2699 const EVP_PKEY *key;
2700 const X509_CRL *crl;
2701 } kExpected[] = {
2702 {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
2703 {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
2704 {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
2705 {cert_obj.get(), nullptr, nullptr},
2706 {cert_obj.get(), nullptr, nullptr},
2707 {cert_obj.get(), nullptr, nullptr},
2708 {cert_obj.get(), rsa_obj.get(), nullptr},
2709 {nullptr, rsa_obj.get(), nullptr},
2710 {nullptr, rsa_obj.get(), nullptr},
2711 {nullptr, rsa_obj.get(), nullptr},
2712 {nullptr, rsa_obj.get(), crl_obj.get()},
2713 {nullptr, nullptr, crl_obj.get()},
2714 {nullptr, nullptr, crl_obj.get()},
2715 };
2716
2717 auto check_info = [](const ExpectedInfo *expected, const X509_INFO *info) {
2718 if (expected->cert != nullptr) {
2719 EXPECT_EQ(0, X509_cmp(expected->cert, info->x509));
2720 } else {
2721 EXPECT_EQ(nullptr, info->x509);
2722 }
2723 if (expected->crl != nullptr) {
2724 EXPECT_EQ(0, X509_CRL_cmp(expected->crl, info->crl));
2725 } else {
2726 EXPECT_EQ(nullptr, info->crl);
2727 }
2728 if (expected->key != nullptr) {
2729 ASSERT_NE(nullptr, info->x_pkey);
2730 // EVP_PKEY_cmp returns one if the keys are equal.
2731 EXPECT_EQ(1, EVP_PKEY_cmp(expected->key, info->x_pkey->dec_pkey));
2732 } else {
2733 EXPECT_EQ(nullptr, info->x_pkey);
2734 }
2735 };
2736
2737 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem.data(), pem.size()));
2738 ASSERT_TRUE(bio);
2739 bssl::UniquePtr<STACK_OF(X509_INFO)> infos(
2740 PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr));
2741 ASSERT_TRUE(infos);
2742 ASSERT_EQ(OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
2743 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
2744 SCOPED_TRACE(i);
2745 check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
2746 }
2747
2748 // Passing an existing stack appends to it.
2749 bio.reset(BIO_new_mem_buf(pem.data(), pem.size()));
2750 ASSERT_TRUE(bio);
2751 ASSERT_EQ(infos.get(),
2752 PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
2753 ASSERT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
2754 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
2755 SCOPED_TRACE(i);
2756 check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
2757 check_info(
2758 &kExpected[i],
2759 sk_X509_INFO_value(infos.get(), i + OPENSSL_ARRAY_SIZE(kExpected)));
2760 }
David Benjamin792c1dc2018-09-23 00:39:53 -05002761
2762 // Gracefully handle errors in both the append and fresh cases.
2763 std::string bad_pem = cert + cert + invalid;
2764
2765 bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size()));
2766 ASSERT_TRUE(bio);
2767 bssl::UniquePtr<STACK_OF(X509_INFO)> infos2(
2768 PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr));
2769 EXPECT_FALSE(infos2);
2770
2771 bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size()));
2772 ASSERT_TRUE(bio);
2773 EXPECT_FALSE(
2774 PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
2775 EXPECT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
David Benjamine7692f52018-09-23 00:06:31 -05002776}
David Benjamin80aa6942018-10-11 12:40:59 -05002777
2778TEST(X509Test, ReadBIOEmpty) {
2779 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(nullptr, 0));
2780 ASSERT_TRUE(bio);
2781
2782 // CPython expects |ASN1_R_HEADER_TOO_LONG| on EOF, to terminate a series of
2783 // certificates.
2784 bssl::UniquePtr<X509> x509(d2i_X509_bio(bio.get(), nullptr));
2785 EXPECT_FALSE(x509);
2786 uint32_t err = ERR_get_error();
2787 EXPECT_EQ(ERR_LIB_ASN1, ERR_GET_LIB(err));
2788 EXPECT_EQ(ASN1_R_HEADER_TOO_LONG, ERR_GET_REASON(err));
2789}
David Benjamin750fea12018-12-05 13:12:48 -06002790
2791TEST(X509Test, ReadBIOOneByte) {
2792 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf("\x30", 1));
2793 ASSERT_TRUE(bio);
2794
2795 // CPython expects |ASN1_R_HEADER_TOO_LONG| on EOF, to terminate a series of
2796 // certificates. This EOF appeared after some data, however, so we do not wish
2797 // to signal EOF.
2798 bssl::UniquePtr<X509> x509(d2i_X509_bio(bio.get(), nullptr));
2799 EXPECT_FALSE(x509);
2800 uint32_t err = ERR_get_error();
2801 EXPECT_EQ(ERR_LIB_ASN1, ERR_GET_LIB(err));
2802 EXPECT_EQ(ASN1_R_NOT_ENOUGH_DATA, ERR_GET_REASON(err));
2803}
2804
2805TEST(X509Test, PartialBIOReturn) {
2806 // Create a filter BIO that only reads and writes one byte at a time.
2807 bssl::UniquePtr<BIO_METHOD> method(BIO_meth_new(0, nullptr));
2808 ASSERT_TRUE(method);
2809 ASSERT_TRUE(BIO_meth_set_create(method.get(), [](BIO *b) -> int {
2810 BIO_set_init(b, 1);
2811 return 1;
2812 }));
2813 ASSERT_TRUE(
2814 BIO_meth_set_read(method.get(), [](BIO *b, char *out, int len) -> int {
2815 return BIO_read(BIO_next(b), out, std::min(len, 1));
2816 }));
2817 ASSERT_TRUE(BIO_meth_set_write(
2818 method.get(), [](BIO *b, const char *in, int len) -> int {
2819 return BIO_write(BIO_next(b), in, std::min(len, 1));
2820 }));
2821
2822 bssl::UniquePtr<BIO> bio(BIO_new(method.get()));
2823 ASSERT_TRUE(bio);
2824 BIO *mem_bio = BIO_new(BIO_s_mem());
2825 ASSERT_TRUE(mem_bio);
2826 BIO_push(bio.get(), mem_bio); // BIO_push takes ownership.
2827
2828 bssl::UniquePtr<X509> cert(CertFromPEM(kLeafPEM));
2829 ASSERT_TRUE(cert);
2830 uint8_t *der = nullptr;
2831 int der_len = i2d_X509(cert.get(), &der);
2832 ASSERT_GT(der_len, 0);
2833 bssl::UniquePtr<uint8_t> free_der(der);
2834
2835 // Write the certificate into the BIO. Though we only write one byte at a
2836 // time, the write should succeed.
2837 ASSERT_EQ(1, i2d_X509_bio(bio.get(), cert.get()));
2838 const uint8_t *der2;
2839 size_t der2_len;
2840 ASSERT_TRUE(BIO_mem_contents(mem_bio, &der2, &der2_len));
2841 EXPECT_EQ(Bytes(der, static_cast<size_t>(der_len)), Bytes(der2, der2_len));
2842
2843 // Read the certificate back out of the BIO. Though we only read one byte at a
2844 // time, the read should succeed.
2845 bssl::UniquePtr<X509> cert2(d2i_X509_bio(bio.get(), nullptr));
2846 ASSERT_TRUE(cert2);
2847 EXPECT_EQ(0, X509_cmp(cert.get(), cert2.get()));
2848}
David Benjaminc60b42b2019-04-16 13:57:11 -05002849
2850TEST(X509Test, CommonNameFallback) {
2851 bssl::UniquePtr<X509> root = CertFromPEM(kSANTypesRoot);
2852 ASSERT_TRUE(root);
2853 bssl::UniquePtr<X509> with_sans = CertFromPEM(kCommonNameWithSANs);
2854 ASSERT_TRUE(with_sans);
2855 bssl::UniquePtr<X509> without_sans = CertFromPEM(kCommonNameWithoutSANs);
2856 ASSERT_TRUE(without_sans);
David Benjamind86eb1b2019-04-17 17:38:52 -05002857 bssl::UniquePtr<X509> with_email = CertFromPEM(kCommonNameWithEmailSAN);
2858 ASSERT_TRUE(with_email);
2859 bssl::UniquePtr<X509> with_ip = CertFromPEM(kCommonNameWithIPSAN);
2860 ASSERT_TRUE(with_ip);
David Benjaminc60b42b2019-04-16 13:57:11 -05002861
2862 auto verify_cert = [&](X509 *leaf, unsigned flags, const char *host) {
David Benjamin523d6c72021-10-01 16:56:12 -04002863 return Verify(leaf, {root.get()}, {}, {}, 0, [&](X509_VERIFY_PARAM *param) {
2864 ASSERT_TRUE(X509_VERIFY_PARAM_set1_host(param, host, strlen(host)));
2865 X509_VERIFY_PARAM_set_hostflags(param, flags);
2866 });
David Benjaminc60b42b2019-04-16 13:57:11 -05002867 };
2868
2869 // By default, the common name is ignored if the SAN list is present but
2870 // otherwise is checked.
2871 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2872 verify_cert(with_sans.get(), 0 /* no flags */, "foo.host1.test"));
2873 EXPECT_EQ(X509_V_OK,
2874 verify_cert(with_sans.get(), 0 /* no flags */, "foo.host2.test"));
2875 EXPECT_EQ(X509_V_OK,
2876 verify_cert(with_sans.get(), 0 /* no flags */, "foo.host3.test"));
2877 EXPECT_EQ(X509_V_OK, verify_cert(without_sans.get(), 0 /* no flags */,
2878 "foo.host1.test"));
David Benjamind86eb1b2019-04-17 17:38:52 -05002879 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2880 verify_cert(with_email.get(), 0 /* no flags */, "foo.host1.test"));
2881 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2882 verify_cert(with_ip.get(), 0 /* no flags */, "foo.host1.test"));
David Benjaminc60b42b2019-04-16 13:57:11 -05002883
David Benjamin923feba2019-04-16 14:28:31 -05002884 // X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT is ignored.
2885 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
David Benjaminc60b42b2019-04-16 13:57:11 -05002886 verify_cert(with_sans.get(), X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT,
2887 "foo.host1.test"));
2888 EXPECT_EQ(X509_V_OK,
2889 verify_cert(with_sans.get(), X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT,
2890 "foo.host2.test"));
2891 EXPECT_EQ(X509_V_OK,
2892 verify_cert(with_sans.get(), X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT,
2893 "foo.host3.test"));
2894 EXPECT_EQ(X509_V_OK, verify_cert(without_sans.get(),
2895 X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT,
2896 "foo.host1.test"));
David Benjamind86eb1b2019-04-17 17:38:52 -05002897 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2898 verify_cert(with_email.get(), X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT,
2899 "foo.host1.test"));
2900 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2901 verify_cert(with_ip.get(), X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT,
2902 "foo.host1.test"));
David Benjaminc60b42b2019-04-16 13:57:11 -05002903
2904 // X509_CHECK_FLAG_NEVER_CHECK_SUBJECT implements the correct behavior: the
2905 // common name is never checked.
2906 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2907 verify_cert(with_sans.get(), X509_CHECK_FLAG_NEVER_CHECK_SUBJECT,
2908 "foo.host1.test"));
2909 EXPECT_EQ(X509_V_OK,
2910 verify_cert(with_sans.get(), X509_CHECK_FLAG_NEVER_CHECK_SUBJECT,
2911 "foo.host2.test"));
2912 EXPECT_EQ(X509_V_OK,
2913 verify_cert(with_sans.get(), X509_CHECK_FLAG_NEVER_CHECK_SUBJECT,
2914 "foo.host3.test"));
2915 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2916 verify_cert(without_sans.get(), X509_CHECK_FLAG_NEVER_CHECK_SUBJECT,
2917 "foo.host1.test"));
David Benjamind86eb1b2019-04-17 17:38:52 -05002918 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2919 verify_cert(with_email.get(), X509_CHECK_FLAG_NEVER_CHECK_SUBJECT,
2920 "foo.host1.test"));
2921 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
2922 verify_cert(with_ip.get(), X509_CHECK_FLAG_NEVER_CHECK_SUBJECT,
2923 "foo.host1.test"));
David Benjaminc60b42b2019-04-16 13:57:11 -05002924}
David Benjaminc67076d2019-04-16 17:39:50 -05002925
2926TEST(X509Test, LooksLikeDNSName) {
2927 static const char *kValid[] = {
2928 "example.com",
2929 "eXample123-.com",
2930 "*.example.com",
2931 "exa_mple.com",
2932 "example.com.",
2933 "project-dev:us-central1:main",
2934 };
2935 static const char *kInvalid[] = {
2936 "-eXample123-.com",
2937 "",
2938 ".",
2939 "*",
2940 "*.",
2941 "example..com",
2942 ".example.com",
2943 "example.com..",
2944 "*foo.example.com",
2945 "foo.*.example.com",
2946 "foo,bar",
2947 };
2948
2949 for (const char *str : kValid) {
2950 SCOPED_TRACE(str);
2951 EXPECT_TRUE(x509v3_looks_like_dns_name(
2952 reinterpret_cast<const uint8_t *>(str), strlen(str)));
2953 }
2954 for (const char *str : kInvalid) {
2955 SCOPED_TRACE(str);
2956 EXPECT_FALSE(x509v3_looks_like_dns_name(
2957 reinterpret_cast<const uint8_t *>(str), strlen(str)));
2958 }
2959}
2960
2961TEST(X509Test, CommonNameAndNameConstraints) {
2962 bssl::UniquePtr<X509> root = CertFromPEM(kSANTypesRoot);
2963 ASSERT_TRUE(root);
2964 bssl::UniquePtr<X509> intermediate = CertFromPEM(kConstrainedIntermediate);
2965 ASSERT_TRUE(intermediate);
2966 bssl::UniquePtr<X509> permitted = CertFromPEM(kCommonNamePermittedLeaf);
2967 ASSERT_TRUE(permitted);
2968 bssl::UniquePtr<X509> not_permitted =
2969 CertFromPEM(kCommonNameNotPermittedLeaf);
2970 ASSERT_TRUE(not_permitted);
2971 bssl::UniquePtr<X509> not_permitted_with_sans =
2972 CertFromPEM(kCommonNameNotPermittedWithSANsLeaf);
2973 ASSERT_TRUE(not_permitted_with_sans);
2974 bssl::UniquePtr<X509> not_dns = CertFromPEM(kCommonNameNotDNSLeaf);
2975 ASSERT_TRUE(not_dns);
2976
2977 auto verify_cert = [&](X509 *leaf, unsigned flags, const char *host) {
2978 return Verify(
David Benjamin523d6c72021-10-01 16:56:12 -04002979 leaf, {root.get()}, {intermediate.get()}, {}, 0,
David Benjaminc67076d2019-04-16 17:39:50 -05002980 [&](X509_VERIFY_PARAM *param) {
2981 ASSERT_TRUE(X509_VERIFY_PARAM_set1_host(param, host, strlen(host)));
2982 X509_VERIFY_PARAM_set_hostflags(param, flags);
2983 });
2984 };
2985
2986 // Certificates which would otherwise trigger the common name fallback are
2987 // rejected whenever there are name constraints. We do this whether or not
2988 // the common name matches the constraints.
2989 EXPECT_EQ(
2990 X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS,
2991 verify_cert(permitted.get(), 0 /* no flags */, kCommonNamePermitted));
2992 EXPECT_EQ(X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS,
2993 verify_cert(not_permitted.get(), 0 /* no flags */,
2994 kCommonNameNotPermitted));
2995
2996 // This occurs even if the built-in name checks aren't used. The caller may
2997 // separately call |X509_check_host|.
2998 EXPECT_EQ(X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS,
2999 Verify(not_permitted.get(), {root.get()}, {intermediate.get()}, {},
David Benjamin523d6c72021-10-01 16:56:12 -04003000 0 /* no flags */, nullptr));
David Benjaminc67076d2019-04-16 17:39:50 -05003001
3002 // If the leaf certificate has SANs, the common name fallback is always
3003 // disabled, so the name constraints do not apply.
3004 EXPECT_EQ(X509_V_OK, Verify(not_permitted_with_sans.get(), {root.get()},
David Benjamin523d6c72021-10-01 16:56:12 -04003005 {intermediate.get()}, {}, 0, nullptr));
David Benjaminc67076d2019-04-16 17:39:50 -05003006 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
3007 verify_cert(not_permitted_with_sans.get(), 0 /* no flags */,
3008 kCommonNameNotPermittedWithSANs));
3009
3010 // If the common name does not look like a DNS name, we apply neither name
3011 // constraints nor common name fallback.
3012 EXPECT_EQ(X509_V_OK, Verify(not_dns.get(), {root.get()}, {intermediate.get()},
David Benjamin523d6c72021-10-01 16:56:12 -04003013 {}, 0, nullptr));
David Benjaminc67076d2019-04-16 17:39:50 -05003014 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
3015 verify_cert(not_dns.get(), 0 /* no flags */, kCommonNameNotDNS));
3016}
Adam Langleybb507832019-09-17 12:56:01 -07003017
3018TEST(X509Test, ServerGatedCryptoEKUs) {
3019 bssl::UniquePtr<X509> root = CertFromPEM(kSANTypesRoot);
3020 ASSERT_TRUE(root);
3021 bssl::UniquePtr<X509> ms_sgc = CertFromPEM(kMicrosoftSGCCert);
3022 ASSERT_TRUE(ms_sgc);
3023 bssl::UniquePtr<X509> ns_sgc = CertFromPEM(kNetscapeSGCCert);
3024 ASSERT_TRUE(ns_sgc);
3025 bssl::UniquePtr<X509> server_eku = CertFromPEM(kServerEKUCert);
3026 ASSERT_TRUE(server_eku);
3027 bssl::UniquePtr<X509> server_eku_plus_ms_sgc =
3028 CertFromPEM(kServerEKUPlusMicrosoftSGCCert);
3029 ASSERT_TRUE(server_eku_plus_ms_sgc);
3030 bssl::UniquePtr<X509> any_eku = CertFromPEM(kAnyEKU);
3031 ASSERT_TRUE(any_eku);
3032 bssl::UniquePtr<X509> no_eku = CertFromPEM(kNoEKU);
3033 ASSERT_TRUE(no_eku);
3034
3035 auto verify_cert = [&root](X509 *leaf) {
3036 return Verify(leaf, {root.get()}, /*intermediates=*/{}, /*crls=*/{},
David Benjamin523d6c72021-10-01 16:56:12 -04003037 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
Adam Langleybb507832019-09-17 12:56:01 -07003038 ASSERT_TRUE(X509_VERIFY_PARAM_set_purpose(
3039 param, X509_PURPOSE_SSL_SERVER));
3040 });
3041 };
3042
3043 // Neither the Microsoft nor Netscape SGC EKU should be sufficient for
3044 // |X509_PURPOSE_SSL_SERVER|. The "any" EKU probably, technically, should be.
3045 // However, we've never accepted it and it's not acceptable in leaf
3046 // certificates by the Baseline, so perhaps we don't need this complexity.
3047 for (X509 *leaf : {ms_sgc.get(), ns_sgc.get(), any_eku.get()}) {
3048 EXPECT_EQ(X509_V_ERR_INVALID_PURPOSE, verify_cert(leaf));
3049 }
3050
3051 // The server-auth EKU is sufficient, and it doesn't matter if an SGC EKU is
3052 // also included. Lastly, not specifying an EKU is also valid.
3053 for (X509 *leaf : {server_eku.get(), server_eku_plus_ms_sgc.get(),
3054 no_eku.get()}) {
3055 EXPECT_EQ(X509_V_OK, verify_cert(leaf));
3056 }
3057}
David Benjaminfd86eaa2020-06-17 15:13:16 -04003058
3059// Test that invalid extensions are rejected by, if not the parser, at least the
3060// verifier.
3061TEST(X509Test, InvalidExtensions) {
3062 bssl::UniquePtr<X509> root = CertFromPEM(
3063 GetTestData("crypto/x509/test/invalid_extension_root.pem").c_str());
3064 ASSERT_TRUE(root);
3065 bssl::UniquePtr<X509> intermediate = CertFromPEM(
3066 GetTestData("crypto/x509/test/invalid_extension_intermediate.pem")
3067 .c_str());
3068 ASSERT_TRUE(intermediate);
3069 bssl::UniquePtr<X509> leaf = CertFromPEM(
3070 GetTestData("crypto/x509/test/invalid_extension_leaf.pem").c_str());
3071 ASSERT_TRUE(leaf);
3072
3073 // Sanity-check that the baseline chain is accepted.
3074 EXPECT_EQ(X509_V_OK,
3075 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}));
3076
3077 static const char *kExtensions[] = {
3078 "authority_key_identifier",
3079 "basic_constraints",
3080 "ext_key_usage",
3081 "key_usage",
3082 "name_constraints",
3083 "subject_alt_name",
3084 "subject_key_identifier",
3085 };
3086 for (const char *ext : kExtensions) {
3087 SCOPED_TRACE(ext);
3088 bssl::UniquePtr<X509> invalid_root = CertFromPEM(
3089 GetTestData((std::string("crypto/x509/test/invalid_extension_root_") +
3090 ext + ".pem")
3091 .c_str())
3092 .c_str());
3093 ASSERT_TRUE(invalid_root);
3094
3095 bssl::UniquePtr<X509> invalid_intermediate = CertFromPEM(
3096 GetTestData(
3097 (std::string("crypto/x509/test/invalid_extension_intermediate_") +
3098 ext + ".pem")
3099 .c_str())
3100 .c_str());
3101 ASSERT_TRUE(invalid_intermediate);
3102
3103 bssl::UniquePtr<X509> invalid_leaf = CertFromPEM(
3104 GetTestData((std::string("crypto/x509/test/invalid_extension_leaf_") +
3105 ext + ".pem")
3106 .c_str())
3107 .c_str());
3108 ASSERT_TRUE(invalid_leaf);
3109
David Benjamin491af102021-10-29 09:05:29 -04003110 bssl::UniquePtr<X509> trailing_leaf = CertFromPEM(
3111 GetTestData((std::string("crypto/x509/test/trailing_data_leaf_") +
3112 ext + ".pem")
3113 .c_str())
3114 .c_str());
3115 ASSERT_TRUE(trailing_leaf);
3116
David Benjaminfd86eaa2020-06-17 15:13:16 -04003117 EXPECT_EQ(
3118 X509_V_ERR_INVALID_EXTENSION,
3119 Verify(invalid_leaf.get(), {root.get()}, {intermediate.get()}, {}));
3120
David Benjamin491af102021-10-29 09:05:29 -04003121 EXPECT_EQ(
3122 X509_V_ERR_INVALID_EXTENSION,
3123 Verify(trailing_leaf.get(), {root.get()}, {intermediate.get()}, {}));
3124
David Benjaminfd86eaa2020-06-17 15:13:16 -04003125 // If the invalid extension is on an intermediate or root,
3126 // |X509_verify_cert| notices by way of being unable to build a path to
3127 // a valid issuer.
3128 EXPECT_EQ(
3129 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
3130 Verify(leaf.get(), {root.get()}, {invalid_intermediate.get()}, {}));
3131 EXPECT_EQ(
3132 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
3133 Verify(leaf.get(), {invalid_root.get()}, {intermediate.get()}, {}));
3134 }
3135}
David Benjamindd86e752020-06-17 21:17:42 -04003136
3137// kExplicitDefaultVersionPEM is an X.509v1 certificate with the version number
3138// encoded explicitly, rather than omitted as required by DER.
David Benjamin991835d2020-10-02 16:21:25 -04003139static const char kExplicitDefaultVersionPEM[] = R"(
3140-----BEGIN CERTIFICATE-----
3141MIIBfTCCASSgAwIBAAIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
3142QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
3143dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
3144BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
3145dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni
3146v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa
3147HPUdfvGULUvPciLBMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb7idQhY5w
3148BnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYfMlJhXnXJ
3149FA==
3150-----END CERTIFICATE-----
3151)";
David Benjamindd86e752020-06-17 21:17:42 -04003152
3153// kNegativeVersionPEM is an X.509 certificate with a negative version number.
David Benjamin991835d2020-10-02 16:21:25 -04003154static const char kNegativeVersionPEM[] = R"(
3155-----BEGIN CERTIFICATE-----
3156MIIBfTCCASSgAwIB/wIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
3157QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
3158dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
3159BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
3160dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni
3161v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa
3162HPUdfvGULUvPciLBMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb7idQhY5w
3163BnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYfMlJhXnXJ
3164FA==
3165-----END CERTIFICATE-----
3166)";
David Benjamindd86e752020-06-17 21:17:42 -04003167
3168// kFutureVersionPEM is an X.509 certificate with a version number value of
3169// three, which is not defined. (v3 has value two).
David Benjamin991835d2020-10-02 16:21:25 -04003170static const char kFutureVersionPEM[] = R"(
3171-----BEGIN CERTIFICATE-----
3172MIIBfTCCASSgAwIBAwIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
3173QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
3174dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
3175BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
3176dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni
3177v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa
3178HPUdfvGULUvPciLBMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb7idQhY5w
3179BnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYfMlJhXnXJ
3180FA==
3181-----END CERTIFICATE-----
3182)";
David Benjamindd86e752020-06-17 21:17:42 -04003183
3184// kOverflowVersionPEM is an X.509 certificate with a version field which
3185// overflows |uint64_t|.
David Benjamin991835d2020-10-02 16:21:25 -04003186static const char kOverflowVersionPEM[] = R"(
3187-----BEGIN CERTIFICATE-----
3188MIIBoDCCAUegJgIkAP//////////////////////////////////////////////
3189AgkA2UwE2kl9v+swCQYHKoZIzj0EATBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwK
3190U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4X
3191DTE0MDQyMzIzMjE1N1oXDTE0MDUyMzIzMjE1N1owRTELMAkGA1UEBhMCQVUxEzAR
3192BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
3193IEx0ZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8eDZSKTNWX
3194a7epHg1G+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQtS89yIsEw
3195CQYHKoZIzj0EAQNIADBFAiEA8qA1XlE6NsOCeZvuJ1CFjnAGdJVX0il0APS+FYdd
3196xAcCIHweeRRqIYPwenRoeV8UmZpotPHLnhVe5h8yUmFedckU
3197-----END CERTIFICATE-----
3198)";
David Benjamindd86e752020-06-17 21:17:42 -04003199
3200// kV1WithExtensionsPEM is an X.509v1 certificate with extensions.
David Benjamin991835d2020-10-02 16:21:25 -04003201static const char kV1WithExtensionsPEM[] = R"(
3202-----BEGIN CERTIFICATE-----
3203MIIByjCCAXECCQDZTATaSX2/6zAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
3204EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0
3205eSBMdGQwHhcNMTQwNDIzMjMyMTU3WhcNMTQwNTIzMjMyMTU3WjBFMQswCQYDVQQG
3206EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk
3207Z2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+
3208Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7x
3209lC1Lz3IiwaNQME4wHQYDVR0OBBYEFKuE0qyrlfCCThZ4B1VXX+QmjYLRMB8GA1Ud
3210IwQYMBaAFKuE0qyrlfCCThZ4B1VXX+QmjYLRMAwGA1UdEwQFMAMBAf8wCQYHKoZI
3211zj0EAQNIADBFAiEA8qA1XlE6NsOCeZvuJ1CFjnAGdJVX0il0APS+FYddxAcCIHwe
3212eRRqIYPwenRoeV8UmZpotPHLnhVe5h8yUmFedckU
3213-----END CERTIFICATE-----
3214)";
David Benjamindd86e752020-06-17 21:17:42 -04003215
3216// kV2WithExtensionsPEM is an X.509v2 certificate with extensions.
David Benjamin991835d2020-10-02 16:21:25 -04003217static const char kV2WithExtensionsPEM[] = R"(
3218-----BEGIN CERTIFICATE-----
3219MIIBzzCCAXagAwIBAQIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
3220QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
3221dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
3222BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
3223dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni
3224v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa
3225HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw
3226HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ
3227BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E
3228BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ=
3229-----END CERTIFICATE-----
3230)";
David Benjamindd86e752020-06-17 21:17:42 -04003231
3232// kV1WithIssuerUniqueIDPEM is an X.509v1 certificate with an issuerUniqueID.
David Benjamin991835d2020-10-02 16:21:25 -04003233static const char kV1WithIssuerUniqueIDPEM[] = R"(
3234-----BEGIN CERTIFICATE-----
3235MIIBgzCCASoCCQDZTATaSX2/6zAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
3236EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0
3237eSBMdGQwHhcNMTQwNDIzMjMyMTU3WhcNMTQwNTIzMjMyMTU3WjBFMQswCQYDVQQG
3238EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk
3239Z2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+
3240Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7x
3241lC1Lz3IiwYEJAAEjRWeJq83vMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb
32427idQhY5wBnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYf
3243MlJhXnXJFA==
3244-----END CERTIFICATE-----
3245)";
David Benjamindd86e752020-06-17 21:17:42 -04003246
3247// kV1WithSubjectUniqueIDPEM is an X.509v1 certificate with an issuerUniqueID.
David Benjamin991835d2020-10-02 16:21:25 -04003248static const char kV1WithSubjectUniqueIDPEM[] = R"(
3249-----BEGIN CERTIFICATE-----
3250MIIBgzCCASoCCQDZTATaSX2/6zAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
3251EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0
3252eSBMdGQwHhcNMTQwNDIzMjMyMTU3WhcNMTQwNTIzMjMyMTU3WjBFMQswCQYDVQQG
3253EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk
3254Z2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+
3255Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7x
3256lC1Lz3IiwYIJAAEjRWeJq83vMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb
32577idQhY5wBnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYf
3258MlJhXnXJFA==
3259-----END CERTIFICATE-----
3260)";
David Benjamindd86e752020-06-17 21:17:42 -04003261
David Benjamin7fd831c2022-04-06 15:38:22 -04003262// kV1CRLWithExtensionsPEM is a v1 CRL with extensions.
3263static const char kV1CRLWithExtensionsPEM[] = R"(
3264-----BEGIN X509 CRL-----
3265MIIBpDCBjTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UECAwK
3266Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJQm9y
3267aW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoA4wDDAKBgNVHRQE
3268AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAnrBKKgvd9x9zwK9rtUvVeFeJ7+LNZEAc
3269+a5oxpPNEsJx6hXoApYEbzXMxuWBQoCs5iEBycSGudct21L+MVf27M38KrWoeOkq
32700a2siqViQZO2Fb/SUFR0k9zb8xl86Zf65lgPplALun0bV/HT7MJcl04Tc4osdsAR
3271eBs5nqTGNEd5AlC1iKHvQZkM//MD51DspKnDpsDiUVi54h9C1SpfZmX8H2Vvdiyu
32720fZ/bPAM3VAGawatf/SyWfBMyKpoPXEG39oAzmjjOj8en82psn7m474IGaho/vBb
3273hl1ms5qQiLYPjm4YELtnXQoFyC72tBjbdFd/ZE9k4CNKDbxFUXFbkw==
3274-----END X509 CRL-----
3275)";
3276
3277// kExplicitDefaultVersionCRLPEM is a v1 CRL with an explicitly-encoded version
3278// field.
3279static const char kExplicitDefaultVersionCRLPEM[] = R"(
3280-----BEGIN X509 CRL-----
3281MIIBlzCBgAIBADANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
3282CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
3283Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaMA0GCSqGSIb3
3284DQEBCwUAA4IBAQCesEoqC933H3PAr2u1S9V4V4nv4s1kQBz5rmjGk80SwnHqFegC
3285lgRvNczG5YFCgKzmIQHJxIa51y3bUv4xV/bszfwqtah46SrRrayKpWJBk7YVv9JQ
3286VHST3NvzGXzpl/rmWA+mUAu6fRtX8dPswlyXThNziix2wBF4GzmepMY0R3kCULWI
3287oe9BmQz/8wPnUOykqcOmwOJRWLniH0LVKl9mZfwfZW92LK7R9n9s8AzdUAZrBq1/
32889LJZ8EzIqmg9cQbf2gDOaOM6Px6fzamyfubjvggZqGj+8FuGXWazmpCItg+ObhgQ
3289u2ddCgXILva0GNt0V39kT2TgI0oNvEVRcVuT
3290-----END X509 CRL-----
3291)";
3292
3293// kV3CRLPEM is a v3 CRL. CRL versions only go up to v2.
3294static const char kV3CRLPEM[] = R"(
3295-----BEGIN X509 CRL-----
3296MIIBpzCBkAIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
3297CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
3298Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoA4wDDAKBgNV
3299HRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAnrBKKgvd9x9zwK9rtUvVeFeJ7+LN
3300ZEAc+a5oxpPNEsJx6hXoApYEbzXMxuWBQoCs5iEBycSGudct21L+MVf27M38KrWo
3301eOkq0a2siqViQZO2Fb/SUFR0k9zb8xl86Zf65lgPplALun0bV/HT7MJcl04Tc4os
3302dsAReBs5nqTGNEd5AlC1iKHvQZkM//MD51DspKnDpsDiUVi54h9C1SpfZmX8H2Vv
3303diyu0fZ/bPAM3VAGawatf/SyWfBMyKpoPXEG39oAzmjjOj8en82psn7m474IGaho
3304/vBbhl1ms5qQiLYPjm4YELtnXQoFyC72tBjbdFd/ZE9k4CNKDbxFUXFbkw==
3305-----END X509 CRL-----
3306)";
3307
3308// kV2CSRPEM is a v2 CSR. CSR versions only go up to v1.
3309static const char kV2CSRPEM[] = R"(
3310-----BEGIN CERTIFICATE REQUEST-----
3311MIHJMHECAQEwDzENMAsGA1UEAwwEVGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEH
3312A0IABJjsayyAQod1J7UJYNT8AH4WWxLdKV0ozhrIz6hCzBAze7AqXWOSH8G+1EWC
3313pSfL3oMQNtBdJS0kpXXaUqEAgTSgADAKBggqhkjOPQQDAgNIADBFAiAUXVaEYATg
33144Cc917T73KBImxh6xyhsA5pKuYpq1S4m9wIhAK+G93HR4ur7Ghel6+zUTvIAsj9e
3315rsn4lSYsqI4OI4ei
3316-----END CERTIFICATE REQUEST-----
3317)";
3318
David Benjamin28c53542022-07-06 15:45:42 -04003319// kV3CSRPEM is a v3 CSR. CSR versions only go up to v1.
3320static const char kV3CSRPEM[] = R"(
3321-----BEGIN CERTIFICATE REQUEST-----
3322MIHJMHECAQIwDzENMAsGA1UEAwwEVGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEH
3323A0IABJjsayyAQod1J7UJYNT8AH4WWxLdKV0ozhrIz6hCzBAze7AqXWOSH8G+1EWC
3324pSfL3oMQNtBdJS0kpXXaUqEAgTSgADAKBggqhkjOPQQDAgNIADBFAiAUXVaEYATg
33254Cc917T73KBImxh6xyhsA5pKuYpq1S4m9wIhAK+G93HR4ur7Ghel6+zUTvIAsj9e
3326rsn4lSYsqI4OI4ei
3327-----END CERTIFICATE REQUEST-----
3328)";
3329
David Benjamin7fd831c2022-04-06 15:38:22 -04003330// Test that the library enforces versions are valid and match the fields
David Benjamindd86e752020-06-17 21:17:42 -04003331// present.
3332TEST(X509Test, InvalidVersion) {
David Benjaminde196122020-07-09 12:01:51 -04003333 // kExplicitDefaultVersionPEM is invalid but, for now, we accept it. See
3334 // https://crbug.com/boringssl/364.
3335 EXPECT_TRUE(CertFromPEM(kExplicitDefaultVersionPEM));
David Benjamin7fd831c2022-04-06 15:38:22 -04003336 EXPECT_TRUE(CRLFromPEM(kExplicitDefaultVersionCRLPEM));
David Benjaminde196122020-07-09 12:01:51 -04003337
David Benjamindd86e752020-06-17 21:17:42 -04003338 EXPECT_FALSE(CertFromPEM(kNegativeVersionPEM));
3339 EXPECT_FALSE(CertFromPEM(kFutureVersionPEM));
3340 EXPECT_FALSE(CertFromPEM(kOverflowVersionPEM));
David Benjamind422d2c2021-07-27 20:11:14 -04003341 EXPECT_FALSE(CertFromPEM(kV1WithExtensionsPEM));
3342 EXPECT_FALSE(CertFromPEM(kV2WithExtensionsPEM));
David Benjamindd86e752020-06-17 21:17:42 -04003343 EXPECT_FALSE(CertFromPEM(kV1WithIssuerUniqueIDPEM));
3344 EXPECT_FALSE(CertFromPEM(kV1WithSubjectUniqueIDPEM));
David Benjamin7fd831c2022-04-06 15:38:22 -04003345 EXPECT_FALSE(CRLFromPEM(kV1CRLWithExtensionsPEM));
3346 EXPECT_FALSE(CRLFromPEM(kV3CRLPEM));
3347 EXPECT_FALSE(CSRFromPEM(kV2CSRPEM));
3348
David Benjamin28c53542022-07-06 15:45:42 -04003349 // kV3CSRPEM is invalid but, for now, we accept it. See
3350 // https://github.com/certbot/certbot/pull/9334
3351 EXPECT_TRUE(CSRFromPEM(kV3CSRPEM));
3352
David Benjamin7fd831c2022-04-06 15:38:22 -04003353 bssl::UniquePtr<X509> x509(X509_new());
3354 ASSERT_TRUE(x509);
3355 EXPECT_FALSE(X509_set_version(x509.get(), -1));
3356 EXPECT_FALSE(X509_set_version(x509.get(), X509_VERSION_3 + 1));
3357 EXPECT_FALSE(X509_set_version(x509.get(), 9999));
3358
3359 bssl::UniquePtr<X509_CRL> crl(X509_CRL_new());
3360 ASSERT_TRUE(crl);
3361 EXPECT_FALSE(X509_CRL_set_version(crl.get(), -1));
3362 EXPECT_FALSE(X509_CRL_set_version(crl.get(), X509_CRL_VERSION_2 + 1));
3363 EXPECT_FALSE(X509_CRL_set_version(crl.get(), 9999));
3364
3365 bssl::UniquePtr<X509_REQ> req(X509_REQ_new());
3366 ASSERT_TRUE(req);
3367 EXPECT_FALSE(X509_REQ_set_version(req.get(), -1));
3368 EXPECT_FALSE(X509_REQ_set_version(req.get(), X509_REQ_VERSION_1 + 1));
3369 EXPECT_FALSE(X509_REQ_set_version(req.get(), 9999));
David Benjamindd86e752020-06-17 21:17:42 -04003370}
David Benjaminca3f2432020-08-31 14:47:49 -04003371
3372// Unlike upstream OpenSSL, we require a non-null store in
3373// |X509_STORE_CTX_init|.
3374TEST(X509Test, NullStore) {
3375 bssl::UniquePtr<X509> leaf(CertFromPEM(kLeafPEM));
3376 ASSERT_TRUE(leaf);
3377 bssl::UniquePtr<X509_STORE_CTX> ctx(X509_STORE_CTX_new());
3378 ASSERT_TRUE(ctx);
3379 EXPECT_FALSE(X509_STORE_CTX_init(ctx.get(), nullptr, leaf.get(), nullptr));
3380}
David Benjaminee4af9e2020-08-31 16:54:47 -04003381
3382TEST(X509Test, BasicConstraints) {
3383 const uint32_t kFlagMask = EXFLAG_CA | EXFLAG_BCONS | EXFLAG_INVALID;
3384
3385 static const struct {
3386 const char *file;
3387 uint32_t flags;
3388 int path_len;
3389 } kTests[] = {
3390 {"basic_constraints_none.pem", 0, -1},
3391 {"basic_constraints_ca.pem", EXFLAG_CA | EXFLAG_BCONS, -1},
3392 {"basic_constraints_ca_pathlen_0.pem", EXFLAG_CA | EXFLAG_BCONS, 0},
3393 {"basic_constraints_ca_pathlen_1.pem", EXFLAG_CA | EXFLAG_BCONS, 1},
3394 {"basic_constraints_ca_pathlen_10.pem", EXFLAG_CA | EXFLAG_BCONS, 10},
3395 {"basic_constraints_leaf.pem", EXFLAG_BCONS, -1},
3396 {"invalid_extension_leaf_basic_constraints.pem", EXFLAG_INVALID, -1},
3397 };
3398
3399 for (const auto &test : kTests) {
3400 SCOPED_TRACE(test.file);
3401
3402 std::string path = "crypto/x509/test/";
3403 path += test.file;
3404
3405 bssl::UniquePtr<X509> cert = CertFromPEM(GetTestData(path.c_str()).c_str());
3406 ASSERT_TRUE(cert);
3407 EXPECT_EQ(test.flags, X509_get_extension_flags(cert.get()) & kFlagMask);
3408 EXPECT_EQ(test.path_len, X509_get_pathlen(cert.get()));
3409 }
3410}
David Benjamin40f49422020-10-23 11:08:41 -04003411
3412// The following strings are test certificates signed by kP256Key and kRSAKey,
3413// with missing, NULL, or invalid algorithm parameters.
3414static const char kP256NoParam[] = R"(
3415-----BEGIN CERTIFICATE-----
3416MIIBIDCBxqADAgECAgIE0jAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRUZXN0MCAX
3417DTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRUZXN0
3418MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6ke
3419DUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMQMA4w
3420DAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNJADBGAiEAqdIiF+bN9Cl44oUeICpy
3421aXd7HqhpVUaglYKw9ChmNUACIQCpMdL0fNkFNDbRww9dSl/y7kBdk/tp16HiqeSy
3422gGzFYg==
3423-----END CERTIFICATE-----
3424)";
3425static const char kP256NullParam[] = R"(
3426-----BEGIN CERTIFICATE-----
3427MIIBJDCByKADAgECAgIE0jAMBggqhkjOPQQDAgUAMA8xDTALBgNVBAMTBFRlc3Qw
3428IBcNMDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMA8xDTALBgNVBAMTBFRl
3429c3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2niv2Wfl74vHg2UikzVl2u3
3430qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYaHPUdfvGULUvPciLBoxAw
3431DjAMBgNVHRMEBTADAQH/MAwGCCqGSM49BAMCBQADSQAwRgIhAKILHmyo+F3Cn/VX
3432UUeSXOQQKX5aLzsQitwwmNF3ZgH3AiEAsYHcrVj/ftmoQIORARkQ/+PrqntXev8r
3433t6uPxHrmpUY=
3434-----END CERTIFICATE-----
3435)";
3436static const char kP256InvalidParam[] = R"(
3437-----BEGIN CERTIFICATE-----
3438MIIBMTCBz6ADAgECAgIE0jATBggqhkjOPQQDAgQHZ2FyYmFnZTAPMQ0wCwYDVQQD
3439EwRUZXN0MCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYD
3440VQQDEwRUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4N
3441lIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1L
3442z3IiwaMQMA4wDAYDVR0TBAUwAwEB/zATBggqhkjOPQQDAgQHZ2FyYmFnZQNIADBF
3443AiAglpDf/YhN89LeJ2WAs/F0SJIrsuhS4uoInIz6WXUiuQIhAIu5Pwhp5E3Pbo8y
3444fLULTZnynuQUULQkRcF7S7T2WpIL
3445-----END CERTIFICATE-----
3446)";
3447static const char kRSANoParam[] = R"(
3448-----BEGIN CERTIFICATE-----
3449MIIBWzCBx6ADAgECAgIE0jALBgkqhkiG9w0BAQswDzENMAsGA1UEAxMEVGVzdDAg
3450Fw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsGA1UEAxMEVGVz
3451dDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8eDZSKTNWXa7ep
3452Hg1G+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQtS89yIsGjEDAO
3453MAwGA1UdEwQFMAMBAf8wCwYJKoZIhvcNAQELA4GBAC1f8W3W0Ao7CPfIBQYDSbPh
3454brZpbxdBU5x27JOS7iSa+Lc9pEH5VCX9vIypHVHXLPEfZ38yIt11eiyrmZB6w62N
3455l9kIeZ6FVPmC30d3sXx70Jjs+ZX9yt7kD1gLyNAQQfeYfa4rORAZT1n2YitD74NY
3456TWUH2ieFP3l+ecj1SeQR
3457-----END CERTIFICATE-----
3458)";
3459static const char kRSANullParam[] = R"(
3460-----BEGIN CERTIFICATE-----
3461MIIBXzCByaADAgECAgIE0jANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRUZXN0
3462MCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRU
3463ZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdr
3464t6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMQ
3465MA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAzVcfIv+Rq1KrMXqIL
3466fPq/cWZjgqFZA1RGaGElNaqp+rkJfamq5tDGzckWpebrK+jjRN7yIlcWDtPpy3Gy
3467seZfvtBDR0TwJm0S/pQl8prKB4wgALcwe3bmi56Rq85nzY5ZLNcP16LQxL+jAAua
3468SwmQUz4bRpckRBj+sIyp1We+pg==
3469-----END CERTIFICATE-----
3470)";
3471static const char kRSAInvalidParam[] = R"(
3472-----BEGIN CERTIFICATE-----
3473MIIBbTCB0KADAgECAgIE0jAUBgkqhkiG9w0BAQsEB2dhcmJhZ2UwDzENMAsGA1UE
3474AxMEVGVzdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsG
3475A1UEAxMEVGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8e
3476DZSKTNWXa7epHg1G+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQt
3477S89yIsGjEDAOMAwGA1UdEwQFMAMBAf8wFAYJKoZIhvcNAQELBAdnYXJiYWdlA4GB
3478AHTJ6cWWjCNrZhqiWWVI3jdK+h5xpRG8jGMXxR4JnjtoYRRusJLOXhmapwCB6fA0
34794vc+66O27v36yDmQX+tIc/hDrTpKNJptU8q3n2VagREvoHhkOTYkcCeS8vmnMtn8
34805OMNZ/ajVwOssw61GcAlScRqEHkZFBoGp7e+QpgB2tf9
3481-----END CERTIFICATE-----
3482)";
3483
3484TEST(X509Test, AlgorithmParameters) {
3485 // P-256 parameters should be omitted, but we accept NULL ones.
3486 bssl::UniquePtr<EVP_PKEY> key = PrivateKeyFromPEM(kP256Key);
3487 ASSERT_TRUE(key);
3488
3489 bssl::UniquePtr<X509> cert = CertFromPEM(kP256NoParam);
3490 ASSERT_TRUE(cert);
3491 EXPECT_TRUE(X509_verify(cert.get(), key.get()));
3492
3493 cert = CertFromPEM(kP256NullParam);
3494 ASSERT_TRUE(cert);
3495 EXPECT_TRUE(X509_verify(cert.get(), key.get()));
3496
3497 cert = CertFromPEM(kP256InvalidParam);
3498 ASSERT_TRUE(cert);
3499 EXPECT_FALSE(X509_verify(cert.get(), key.get()));
3500 uint32_t err = ERR_get_error();
3501 EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
3502 EXPECT_EQ(X509_R_INVALID_PARAMETER, ERR_GET_REASON(err));
3503
3504 // RSA parameters should be NULL, but we accept omitted ones.
3505 key = PrivateKeyFromPEM(kRSAKey);
3506 ASSERT_TRUE(key);
3507
3508 cert = CertFromPEM(kRSANoParam);
3509 ASSERT_TRUE(cert);
3510 EXPECT_TRUE(X509_verify(cert.get(), key.get()));
3511
3512 cert = CertFromPEM(kRSANullParam);
3513 ASSERT_TRUE(cert);
3514 EXPECT_TRUE(X509_verify(cert.get(), key.get()));
3515
3516 cert = CertFromPEM(kRSAInvalidParam);
3517 ASSERT_TRUE(cert);
3518 EXPECT_FALSE(X509_verify(cert.get(), key.get()));
3519 err = ERR_get_error();
3520 EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
3521 EXPECT_EQ(X509_R_INVALID_PARAMETER, ERR_GET_REASON(err));
3522}
David Benjaminaa4ecb42020-10-29 18:28:45 -04003523
3524TEST(X509Test, GeneralName) {
3525 const std::vector<uint8_t> kNames[] = {
3526 // [0] {
3527 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
3528 // [0] {
3529 // SEQUENCE {}
3530 // }
3531 // }
3532 {0xa0, 0x13, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
3533 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x02, 0x30, 0x00},
3534 // [0] {
3535 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
3536 // [0] {
3537 // [APPLICATION 0] {}
3538 // }
3539 // }
3540 {0xa0, 0x13, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
3541 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x02, 0x60, 0x00},
3542 // [0] {
3543 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
3544 // [0] {
3545 // UTF8String { "a" }
3546 // }
3547 // }
3548 {0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
3549 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x0c, 0x01, 0x61},
3550 // [0] {
3551 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.2 }
3552 // [0] {
3553 // UTF8String { "a" }
3554 // }
3555 // }
3556 {0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
3557 0x01, 0x84, 0xb7, 0x09, 0x02, 0x02, 0xa0, 0x03, 0x0c, 0x01, 0x61},
3558 // [0] {
3559 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
3560 // [0] {
3561 // UTF8String { "b" }
3562 // }
3563 // }
3564 {0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
3565 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x0c, 0x01, 0x62},
3566 // [0] {
3567 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
3568 // [0] {
3569 // BOOLEAN { TRUE }
3570 // }
3571 // }
3572 {0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
3573 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x01, 0x01, 0xff},
3574 // [0] {
3575 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
3576 // [0] {
3577 // BOOLEAN { FALSE }
3578 // }
3579 // }
3580 {0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
3581 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x01, 0x01, 0x00},
3582 // [1 PRIMITIVE] { "a" }
3583 {0x81, 0x01, 0x61},
3584 // [1 PRIMITIVE] { "b" }
3585 {0x81, 0x01, 0x62},
3586 // [2 PRIMITIVE] { "a" }
3587 {0x82, 0x01, 0x61},
3588 // [2 PRIMITIVE] { "b" }
3589 {0x82, 0x01, 0x62},
3590 // [4] {
3591 // SEQUENCE {
3592 // SET {
3593 // SEQUENCE {
3594 // # commonName
3595 // OBJECT_IDENTIFIER { 2.5.4.3 }
3596 // UTF8String { "a" }
3597 // }
3598 // }
3599 // }
3600 // }
3601 {0xa4, 0x0e, 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04,
3602 0x03, 0x0c, 0x01, 0x61},
3603 // [4] {
3604 // SEQUENCE {
3605 // SET {
3606 // SEQUENCE {
3607 // # commonName
3608 // OBJECT_IDENTIFIER { 2.5.4.3 }
3609 // UTF8String { "b" }
3610 // }
3611 // }
3612 // }
3613 // }
3614 {0xa4, 0x0e, 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04,
3615 0x03, 0x0c, 0x01, 0x62},
3616 // [5] {
3617 // [1] {
3618 // UTF8String { "a" }
3619 // }
3620 // }
3621 {0xa5, 0x05, 0xa1, 0x03, 0x0c, 0x01, 0x61},
3622 // [5] {
3623 // [1] {
3624 // UTF8String { "b" }
3625 // }
3626 // }
3627 {0xa5, 0x05, 0xa1, 0x03, 0x0c, 0x01, 0x62},
3628 // [5] {
3629 // [0] {
3630 // UTF8String {}
3631 // }
3632 // [1] {
3633 // UTF8String { "a" }
3634 // }
3635 // }
3636 {0xa5, 0x09, 0xa0, 0x02, 0x0c, 0x00, 0xa1, 0x03, 0x0c, 0x01, 0x61},
3637 // [5] {
3638 // [0] {
3639 // UTF8String { "a" }
3640 // }
3641 // [1] {
3642 // UTF8String { "a" }
3643 // }
3644 // }
3645 {0xa5, 0x0a, 0xa0, 0x03, 0x0c, 0x01, 0x61, 0xa1, 0x03, 0x0c, 0x01, 0x61},
3646 // [5] {
3647 // [0] {
3648 // UTF8String { "b" }
3649 // }
3650 // [1] {
3651 // UTF8String { "a" }
3652 // }
3653 // }
3654 {0xa5, 0x0a, 0xa0, 0x03, 0x0c, 0x01, 0x62, 0xa1, 0x03, 0x0c, 0x01, 0x61},
3655 // [6 PRIMITIVE] { "a" }
3656 {0x86, 0x01, 0x61},
3657 // [6 PRIMITIVE] { "b" }
3658 {0x86, 0x01, 0x62},
3659 // [7 PRIMITIVE] { `11111111` }
3660 {0x87, 0x04, 0x11, 0x11, 0x11, 0x11},
3661 // [7 PRIMITIVE] { `22222222`}
3662 {0x87, 0x04, 0x22, 0x22, 0x22, 0x22},
3663 // [7 PRIMITIVE] { `11111111111111111111111111111111` }
3664 {0x87, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
3665 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
3666 // [7 PRIMITIVE] { `22222222222222222222222222222222` }
3667 {0x87, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
3668 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},
3669 // [8 PRIMITIVE] { 1.2.840.113554.4.1.72585.2.1 }
3670 {0x88, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
3671 0x09, 0x02, 0x01},
3672 // [8 PRIMITIVE] { 1.2.840.113554.4.1.72585.2.2 }
3673 {0x88, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
3674 0x09, 0x02, 0x02},
3675 };
3676
3677 // Every name should be equal to itself and not equal to any others.
3678 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kNames); i++) {
3679 SCOPED_TRACE(Bytes(kNames[i]));
3680
3681 const uint8_t *ptr = kNames[i].data();
3682 bssl::UniquePtr<GENERAL_NAME> a(
3683 d2i_GENERAL_NAME(nullptr, &ptr, kNames[i].size()));
3684 ASSERT_TRUE(a);
David Benjamin60926d32020-12-15 13:28:24 -05003685 ASSERT_EQ(ptr, kNames[i].data() + kNames[i].size());
David Benjaminaa4ecb42020-10-29 18:28:45 -04003686
3687 for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(kNames); j++) {
3688 SCOPED_TRACE(Bytes(kNames[j]));
3689
3690 ptr = kNames[j].data();
3691 bssl::UniquePtr<GENERAL_NAME> b(
3692 d2i_GENERAL_NAME(nullptr, &ptr, kNames[j].size()));
3693 ASSERT_TRUE(b);
David Benjamin60926d32020-12-15 13:28:24 -05003694 ASSERT_EQ(ptr, kNames[j].data() + kNames[j].size());
David Benjaminaa4ecb42020-10-29 18:28:45 -04003695
3696 if (i == j) {
3697 EXPECT_EQ(GENERAL_NAME_cmp(a.get(), b.get()), 0);
3698 } else {
3699 EXPECT_NE(GENERAL_NAME_cmp(a.get(), b.get()), 0);
3700 }
3701 }
3702 }
3703}
David Benjaminac85c032021-03-21 12:24:16 -04003704
3705// Test that extracting fields of an |X509_ALGOR| works correctly.
3706TEST(X509Test, X509AlgorExtract) {
3707 static const char kTestOID[] = "1.2.840.113554.4.1.72585.2";
3708 const struct {
3709 int param_type;
3710 std::vector<uint8_t> param_der;
3711 } kTests[] = {
3712 // No parameter.
3713 {V_ASN1_UNDEF, {}},
3714 // BOOLEAN { TRUE }
3715 {V_ASN1_BOOLEAN, {0x01, 0x01, 0xff}},
3716 // BOOLEAN { FALSE }
3717 {V_ASN1_BOOLEAN, {0x01, 0x01, 0x00}},
3718 // OCTET_STRING { "a" }
3719 {V_ASN1_OCTET_STRING, {0x04, 0x01, 0x61}},
3720 // BIT_STRING { `01` `00` }
3721 {V_ASN1_BIT_STRING, {0x03, 0x02, 0x01, 0x00}},
3722 // INTEGER { -1 }
3723 {V_ASN1_INTEGER, {0x02, 0x01, 0xff}},
3724 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2 }
3725 {V_ASN1_OBJECT,
3726 {0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
3727 0x09, 0x02}},
3728 // NULL {}
3729 {V_ASN1_NULL, {0x05, 0x00}},
3730 // SEQUENCE {}
3731 {V_ASN1_SEQUENCE, {0x30, 0x00}},
3732 // SET {}
3733 {V_ASN1_SET, {0x31, 0x00}},
3734 // [0] { UTF8String { "a" } }
3735 {V_ASN1_OTHER, {0xa0, 0x03, 0x0c, 0x01, 0x61}},
3736 };
3737 for (const auto &t : kTests) {
3738 SCOPED_TRACE(Bytes(t.param_der));
3739
3740 // Assemble an AlgorithmIdentifier with the parameter.
3741 bssl::ScopedCBB cbb;
3742 CBB seq, oid;
3743 ASSERT_TRUE(CBB_init(cbb.get(), 64));
3744 ASSERT_TRUE(CBB_add_asn1(cbb.get(), &seq, CBS_ASN1_SEQUENCE));
3745 ASSERT_TRUE(CBB_add_asn1(&seq, &oid, CBS_ASN1_OBJECT));
3746 ASSERT_TRUE(CBB_add_asn1_oid_from_text(&oid, kTestOID, strlen(kTestOID)));
3747 ASSERT_TRUE(CBB_add_bytes(&seq, t.param_der.data(), t.param_der.size()));
3748 ASSERT_TRUE(CBB_flush(cbb.get()));
3749
3750 const uint8_t *ptr = CBB_data(cbb.get());
3751 bssl::UniquePtr<X509_ALGOR> alg(
3752 d2i_X509_ALGOR(nullptr, &ptr, CBB_len(cbb.get())));
3753 ASSERT_TRUE(alg);
3754
3755 const ASN1_OBJECT *obj;
3756 int param_type;
3757 const void *param_value;
3758 X509_ALGOR_get0(&obj, &param_type, &param_value, alg.get());
3759
3760 EXPECT_EQ(param_type, t.param_type);
3761 char oid_buf[sizeof(kTestOID)];
3762 ASSERT_EQ(int(sizeof(oid_buf) - 1),
3763 OBJ_obj2txt(oid_buf, sizeof(oid_buf), obj,
3764 /*always_return_oid=*/1));
3765 EXPECT_STREQ(oid_buf, kTestOID);
3766
3767 // |param_type| and |param_value| must be consistent with |ASN1_TYPE|.
3768 if (param_type == V_ASN1_UNDEF) {
3769 EXPECT_EQ(nullptr, param_value);
3770 } else {
3771 bssl::UniquePtr<ASN1_TYPE> param(ASN1_TYPE_new());
3772 ASSERT_TRUE(param);
3773 ASSERT_TRUE(ASN1_TYPE_set1(param.get(), param_type, param_value));
3774
3775 uint8_t *param_der = nullptr;
3776 int param_len = i2d_ASN1_TYPE(param.get(), &param_der);
3777 ASSERT_GE(param_len, 0);
3778 bssl::UniquePtr<uint8_t> free_param_der(param_der);
3779
3780 EXPECT_EQ(Bytes(param_der, param_len), Bytes(t.param_der));
3781 }
3782 }
3783}
David Benjaminab7811e2021-04-20 14:26:36 -04003784
3785// Test the various |X509_ATTRIBUTE| creation functions.
3786TEST(X509Test, Attribute) {
David Benjamin8648c532021-08-19 18:02:37 -04003787 // The friendlyName attribute has a BMPString value. See RFC 2985,
David Benjaminab7811e2021-04-20 14:26:36 -04003788 // section 5.5.1.
3789 static const uint8_t kTest1[] = {0x26, 0x03}; // U+2603 SNOWMAN
3790 static const uint8_t kTest1UTF8[] = {0xe2, 0x98, 0x83};
3791 static const uint8_t kTest2[] = {0, 't', 0, 'e', 0, 's', 0, 't'};
3792
3793 auto check_attribute = [&](X509_ATTRIBUTE *attr, bool has_test2) {
3794 EXPECT_EQ(NID_friendlyName, OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)));
3795
3796 EXPECT_EQ(has_test2 ? 2 : 1, X509_ATTRIBUTE_count(attr));
3797
3798 // The first attribute should contain |kTest1|.
3799 const ASN1_TYPE *value = X509_ATTRIBUTE_get0_type(attr, 0);
3800 ASSERT_TRUE(value);
3801 EXPECT_EQ(V_ASN1_BMPSTRING, value->type);
3802 EXPECT_EQ(Bytes(kTest1),
3803 Bytes(ASN1_STRING_get0_data(value->value.bmpstring),
3804 ASN1_STRING_length(value->value.bmpstring)));
3805
3806 // |X509_ATTRIBUTE_get0_data| requires the type match.
3807 EXPECT_FALSE(
3808 X509_ATTRIBUTE_get0_data(attr, 0, V_ASN1_OCTET_STRING, nullptr));
3809 const ASN1_BMPSTRING *bmpstring = static_cast<const ASN1_BMPSTRING *>(
3810 X509_ATTRIBUTE_get0_data(attr, 0, V_ASN1_BMPSTRING, nullptr));
3811 ASSERT_TRUE(bmpstring);
3812 EXPECT_EQ(Bytes(kTest1), Bytes(ASN1_STRING_get0_data(bmpstring),
3813 ASN1_STRING_length(bmpstring)));
3814
3815 if (has_test2) {
3816 value = X509_ATTRIBUTE_get0_type(attr, 1);
3817 ASSERT_TRUE(value);
3818 EXPECT_EQ(V_ASN1_BMPSTRING, value->type);
3819 EXPECT_EQ(Bytes(kTest2),
3820 Bytes(ASN1_STRING_get0_data(value->value.bmpstring),
3821 ASN1_STRING_length(value->value.bmpstring)));
3822 } else {
3823 EXPECT_FALSE(X509_ATTRIBUTE_get0_type(attr, 1));
3824 }
3825
3826 EXPECT_FALSE(X509_ATTRIBUTE_get0_type(attr, 2));
3827 };
3828
3829 bssl::UniquePtr<ASN1_STRING> str(ASN1_STRING_type_new(V_ASN1_BMPSTRING));
3830 ASSERT_TRUE(str);
3831 ASSERT_TRUE(ASN1_STRING_set(str.get(), kTest1, sizeof(kTest1)));
3832
3833 // Test |X509_ATTRIBUTE_create|.
3834 bssl::UniquePtr<X509_ATTRIBUTE> attr(
3835 X509_ATTRIBUTE_create(NID_friendlyName, V_ASN1_BMPSTRING, str.get()));
3836 ASSERT_TRUE(attr);
3837 str.release(); // |X509_ATTRIBUTE_create| takes ownership on success.
3838 check_attribute(attr.get(), /*has_test2=*/false);
3839
3840 // Test the |MBSTRING_*| form of |X509_ATTRIBUTE_set1_data|.
3841 attr.reset(X509_ATTRIBUTE_new());
3842 ASSERT_TRUE(attr);
3843 ASSERT_TRUE(
3844 X509_ATTRIBUTE_set1_object(attr.get(), OBJ_nid2obj(NID_friendlyName)));
3845 ASSERT_TRUE(X509_ATTRIBUTE_set1_data(attr.get(), MBSTRING_UTF8, kTest1UTF8,
3846 sizeof(kTest1UTF8)));
3847 check_attribute(attr.get(), /*has_test2=*/false);
3848
3849 // Test the |ASN1_STRING| form of |X509_ATTRIBUTE_set1_data|.
3850 ASSERT_TRUE(X509_ATTRIBUTE_set1_data(attr.get(), V_ASN1_BMPSTRING, kTest2,
3851 sizeof(kTest2)));
3852 check_attribute(attr.get(), /*has_test2=*/true);
3853
3854 // Test the |ASN1_TYPE| form of |X509_ATTRIBUTE_set1_data|.
3855 attr.reset(X509_ATTRIBUTE_new());
3856 ASSERT_TRUE(attr);
3857 ASSERT_TRUE(
3858 X509_ATTRIBUTE_set1_object(attr.get(), OBJ_nid2obj(NID_friendlyName)));
3859 str.reset(ASN1_STRING_type_new(V_ASN1_BMPSTRING));
3860 ASSERT_TRUE(str);
3861 ASSERT_TRUE(ASN1_STRING_set(str.get(), kTest1, sizeof(kTest1)));
3862 ASSERT_TRUE(
3863 X509_ATTRIBUTE_set1_data(attr.get(), V_ASN1_BMPSTRING, str.get(), -1));
3864 check_attribute(attr.get(), /*has_test2=*/false);
3865}
David Benjamin8f5eb802021-10-01 16:40:31 -04003866
3867// Test that, by default, |X509_V_FLAG_TRUSTED_FIRST| is set, which means we'll
3868// skip over server-sent expired intermediates when there is a local trust
3869// anchor that works better.
3870TEST(X509Test, TrustedFirst) {
3871 // Generate the following certificates:
3872 //
3873 // Root 2 (in store, expired)
3874 // |
3875 // Root 1 (in store) Root 1 (cross-sign)
3876 // \ /
3877 // Intermediate
3878 // |
3879 // Leaf
3880 bssl::UniquePtr<EVP_PKEY> key = PrivateKeyFromPEM(kP256Key);
3881 ASSERT_TRUE(key);
3882
3883 bssl::UniquePtr<X509> root2 =
3884 MakeTestCert("Root 2", "Root 2", key.get(), /*is_ca=*/true);
3885 ASSERT_TRUE(root2);
3886 ASSERT_TRUE(ASN1_TIME_adj(X509_getm_notAfter(root2.get()), kReferenceTime,
3887 /*offset_day=*/0,
3888 /*offset_sec=*/-1));
3889 ASSERT_TRUE(X509_sign(root2.get(), key.get(), EVP_sha256()));
3890
3891 bssl::UniquePtr<X509> root1 =
3892 MakeTestCert("Root 1", "Root 1", key.get(), /*is_ca=*/true);
3893 ASSERT_TRUE(root1);
3894 ASSERT_TRUE(X509_sign(root1.get(), key.get(), EVP_sha256()));
3895
3896 bssl::UniquePtr<X509> root1_cross =
3897 MakeTestCert("Root 2", "Root 1", key.get(), /*is_ca=*/true);
3898 ASSERT_TRUE(root1_cross);
3899 ASSERT_TRUE(X509_sign(root1_cross.get(), key.get(), EVP_sha256()));
3900
3901 bssl::UniquePtr<X509> intermediate =
3902 MakeTestCert("Root 1", "Intermediate", key.get(), /*is_ca=*/true);
3903 ASSERT_TRUE(intermediate);
3904 ASSERT_TRUE(X509_sign(intermediate.get(), key.get(), EVP_sha256()));
3905
3906 bssl::UniquePtr<X509> leaf =
3907 MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false);
3908 ASSERT_TRUE(leaf);
3909 ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256()));
3910
3911 // As a control, confirm that |leaf| -> |intermediate| -> |root1| is valid,
3912 // but the path through |root1_cross| is expired.
3913 EXPECT_EQ(X509_V_OK,
3914 Verify(leaf.get(), {root1.get()}, {intermediate.get()}, {}));
3915 EXPECT_EQ(X509_V_ERR_CERT_HAS_EXPIRED,
3916 Verify(leaf.get(), {root2.get()},
3917 {intermediate.get(), root1_cross.get()}, {}));
3918
3919 // By default, we should find the |leaf| -> |intermediate| -> |root2| chain,
3920 // skipping |root1_cross|.
3921 EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root1.get(), root2.get()},
3922 {intermediate.get(), root1_cross.get()}, {}));
3923
3924 // When |X509_V_FLAG_TRUSTED_FIRST| is disabled, we get stuck on the expired
3925 // intermediate. Note we need the callback to clear the flag. Setting |flags|
3926 // to zero only skips setting new flags.
3927 //
3928 // This test exists to confirm our current behavior, but these modes are just
3929 // workarounds for not having an actual path-building verifier. If we fix it,
3930 // this test can be removed.
3931 EXPECT_EQ(X509_V_ERR_CERT_HAS_EXPIRED,
3932 Verify(leaf.get(), {root1.get(), root2.get()},
3933 {intermediate.get(), root1_cross.get()}, {}, /*flags=*/0,
3934 [&](X509_VERIFY_PARAM *param) {
3935 X509_VERIFY_PARAM_clear_flags(param,
3936 X509_V_FLAG_TRUSTED_FIRST);
3937 }));
3938
3939 // Even when |X509_V_FLAG_TRUSTED_FIRST| is disabled, if |root2| is not
3940 // trusted, the alt chains logic recovers the path.
3941 EXPECT_EQ(
3942 X509_V_OK,
3943 Verify(leaf.get(), {root1.get()}, {intermediate.get(), root1_cross.get()},
3944 {}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
3945 X509_VERIFY_PARAM_clear_flags(param, X509_V_FLAG_TRUSTED_FIRST);
3946 }));
3947}
David Benjamina70edd42021-10-29 09:05:30 -04003948
David Benjamineccd1032022-08-12 15:12:29 -04003949// Test that notBefore and notAfter checks work correctly.
3950TEST(X509Test, Expiry) {
3951 bssl::UniquePtr<EVP_PKEY> key = PrivateKeyFromPEM(kP256Key);
3952 ASSERT_TRUE(key);
3953
3954 // The following are measured in seconds relative to kReferenceTime. The
3955 // validity periods are staggered so we can independently test both leaf and
3956 // root time checks.
3957 const time_t kSecondsInDay = 24 * 3600;
3958 const time_t kRootStart = -30 * kSecondsInDay;
3959 const time_t kIntermediateStart = -20 * kSecondsInDay;
3960 const time_t kLeafStart = -10 * kSecondsInDay;
3961 const time_t kIntermediateEnd = 10 * kSecondsInDay;
3962 const time_t kLeafEnd = 20 * kSecondsInDay;
3963 const time_t kRootEnd = 30 * kSecondsInDay;
3964
3965 bssl::UniquePtr<X509> root =
3966 MakeTestCert("Root", "Root", key.get(), /*is_ca=*/true);
3967 ASSERT_TRUE(root);
3968 ASSERT_TRUE(ASN1_TIME_adj(X509_getm_notBefore(root.get()), kReferenceTime,
3969 /*offset_day=*/0,
3970 /*offset_sec=*/kRootStart));
3971 ASSERT_TRUE(ASN1_TIME_adj(X509_getm_notAfter(root.get()), kReferenceTime,
3972 /*offset_day=*/0,
3973 /*offset_sec=*/kRootEnd));
3974 ASSERT_TRUE(X509_sign(root.get(), key.get(), EVP_sha256()));
3975
3976 bssl::UniquePtr<X509> intermediate =
3977 MakeTestCert("Root", "Intermediate", key.get(), /*is_ca=*/true);
3978 ASSERT_TRUE(intermediate);
3979 ASSERT_TRUE(ASN1_TIME_adj(X509_getm_notBefore(intermediate.get()),
3980 kReferenceTime,
3981 /*offset_day=*/0,
3982 /*offset_sec=*/kIntermediateStart));
3983 ASSERT_TRUE(ASN1_TIME_adj(X509_getm_notAfter(intermediate.get()),
3984 kReferenceTime,
3985 /*offset_day=*/0,
3986 /*offset_sec=*/kIntermediateEnd));
3987 ASSERT_TRUE(X509_sign(intermediate.get(), key.get(), EVP_sha256()));
3988
3989 bssl::UniquePtr<X509> leaf =
3990 MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false);
3991 ASSERT_TRUE(leaf);
3992 ASSERT_TRUE(ASN1_TIME_adj(X509_getm_notBefore(leaf.get()), kReferenceTime,
3993 /*offset_day=*/0,
3994 /*offset_sec=*/kLeafStart));
3995 ASSERT_TRUE(ASN1_TIME_adj(X509_getm_notAfter(leaf.get()), kReferenceTime,
3996 /*offset_day=*/0,
3997 /*offset_sec=*/kLeafEnd));
3998 ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256()));
3999
4000 struct VerifyAt {
4001 time_t time;
4002 void operator()(X509_VERIFY_PARAM *param) const {
4003 X509_VERIFY_PARAM_set_time(param, time);
4004 }
4005 };
4006
4007 for (bool check_time : {true, false}) {
4008 SCOPED_TRACE(check_time);
4009 unsigned long flags = check_time ? 0 : X509_V_FLAG_NO_CHECK_TIME;
4010 int not_yet_valid = check_time ? X509_V_ERR_CERT_NOT_YET_VALID : X509_V_OK;
4011 int has_expired = check_time ? X509_V_ERR_CERT_HAS_EXPIRED : X509_V_OK;
4012
4013 EXPECT_EQ(not_yet_valid,
4014 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, flags,
4015 VerifyAt{kReferenceTime + kRootStart - 1}));
4016 EXPECT_EQ(not_yet_valid,
4017 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, flags,
4018 VerifyAt{kReferenceTime + kIntermediateStart - 1}));
4019 EXPECT_EQ(not_yet_valid,
4020 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, flags,
4021 VerifyAt{kReferenceTime + kLeafStart - 1}));
4022
4023 EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()},
4024 {}, flags, VerifyAt{kReferenceTime}));
4025
4026 EXPECT_EQ(has_expired,
4027 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, flags,
4028 VerifyAt{kReferenceTime + kRootEnd + 1}));
4029 EXPECT_EQ(has_expired,
4030 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, flags,
4031 VerifyAt{kReferenceTime + kIntermediateEnd + 1}));
4032 EXPECT_EQ(has_expired,
4033 Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, flags,
4034 VerifyAt{kReferenceTime + kLeafEnd + 1}));
4035 }
4036}
4037
David Benjamina70edd42021-10-29 09:05:30 -04004038// kConstructedBitString is an X.509 certificate where the signature is encoded
4039// as a BER constructed BIT STRING. Note that, while OpenSSL's parser accepts
4040// this input, it interprets the value incorrectly.
4041static const char kConstructedBitString[] = R"(
4042-----BEGIN CERTIFICATE-----
4043MIIBJTCBxqADAgECAgIE0jAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRUZXN0MCAX
4044DTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRUZXN0
4045MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6ke
4046DUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMQMA4w
4047DAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAiNOAyQAMEYCIQCp0iIX5s30KXjihR4g
4048KnJpd3seqGlVRqCVgrD0KGYDJgA1QAIhAKkx0vR82QU0NtHDD11KX/LuQF2T+2nX
4049oeKp5LKAbMVi
4050-----END CERTIFICATE-----
4051)";
4052
4053// kConstructedOctetString is an X.509 certificate where an extension is encoded
4054// as a BER constructed OCTET STRING.
4055static const char kConstructedOctetString[] = R"(
4056-----BEGIN CERTIFICATE-----
4057MIIBJDCByqADAgECAgIE0jAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRUZXN0MCAX
4058DTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRUZXN0
4059MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6ke
4060DUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMUMBIw
4061EAYDVR0TJAkEAzADAQQCAf8wCgYIKoZIzj0EAwIDSQAwRgIhAKnSIhfmzfQpeOKF
4062HiAqcml3ex6oaVVGoJWCsPQoZjVAAiEAqTHS9HzZBTQ20cMPXUpf8u5AXZP7adeh
40634qnksoBsxWI=
4064-----END CERTIFICATE-----
4065)";
4066
David Benjaminee510f52021-10-29 09:05:31 -04004067// kIndefiniteLength is an X.509 certificate where the outermost SEQUENCE uses
4068// BER indefinite-length encoding.
4069static const char kIndefiniteLength[] = R"(
4070-----BEGIN CERTIFICATE-----
4071MIAwgcagAwIBAgICBNIwCgYIKoZIzj0EAwIwDzENMAsGA1UEAxMEVGVzdDAgFw0w
4072MDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsGA1UEAxMEVGVzdDBZ
4073MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8eDZSKTNWXa7epHg1G
4074+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQtS89yIsGjEDAOMAwG
4075A1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAKnSIhfmzfQpeOKFHiAqcml3
4076ex6oaVVGoJWCsPQoZjVAAiEAqTHS9HzZBTQ20cMPXUpf8u5AXZP7adeh4qnksoBs
4077xWIAAA==
4078-----END CERTIFICATE-----
4079)";
4080
David Benjamin13c67c92021-10-29 09:05:32 -04004081// kNonZeroPadding is an X.09 certificate where the BIT STRING signature field
4082// has non-zero padding values.
4083static const char kNonZeroPadding[] = R"(
4084-----BEGIN CERTIFICATE-----
4085MIIB0DCCAXagAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
4086QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
4087dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
4088BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
4089dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni
4090v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa
4091HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw
4092HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ
4093BgcqhkjOPQQBA0kBMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E
4094BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQB
4095-----END CERTIFICATE-----
4096)";
4097
David Benjamin657c69b2021-10-30 13:16:39 -04004098// kHighTagNumber is an X.509 certificate where the outermost SEQUENCE tag uses
4099// high tag number form.
4100static const char kHighTagNumber[] = R"(
4101-----BEGIN CERTIFICATE-----
4102PxCCASAwgcagAwIBAgICBNIwCgYIKoZIzj0EAwIwDzENMAsGA1UEAxMEVGVzdDAg
4103Fw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsGA1UEAxMEVGVz
4104dDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8eDZSKTNWXa7ep
4105Hg1G+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQtS89yIsGjEDAO
4106MAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAKnSIhfmzfQpeOKFHiAq
4107cml3ex6oaVVGoJWCsPQoZjVAAiEAqTHS9HzZBTQ20cMPXUpf8u5AXZP7adeh4qnk
4108soBsxWI=
4109-----END CERTIFICATE-----
4110)";
4111
David Benjamina70edd42021-10-29 09:05:30 -04004112TEST(X509Test, BER) {
4113 // Constructed strings are forbidden in DER.
4114 EXPECT_FALSE(CertFromPEM(kConstructedBitString));
4115 EXPECT_FALSE(CertFromPEM(kConstructedOctetString));
David Benjaminee510f52021-10-29 09:05:31 -04004116 // Indefinite lengths are forbidden in DER.
4117 EXPECT_FALSE(CertFromPEM(kIndefiniteLength));
David Benjamin13c67c92021-10-29 09:05:32 -04004118 // Padding bits in BIT STRINGs must be zero in BER.
4119 EXPECT_FALSE(CertFromPEM(kNonZeroPadding));
David Benjamin657c69b2021-10-30 13:16:39 -04004120 // Tags must be minimal in both BER and DER, though many BER decoders
4121 // incorrectly support non-minimal tags.
4122 EXPECT_FALSE(CertFromPEM(kHighTagNumber));
David Benjamina70edd42021-10-29 09:05:30 -04004123}
David Benjamin405c7882021-12-10 23:57:34 -05004124
4125TEST(X509Test, Names) {
4126 bssl::UniquePtr<EVP_PKEY> key = PrivateKeyFromPEM(kP256Key);
4127 ASSERT_TRUE(key);
4128 bssl::UniquePtr<X509> root =
4129 MakeTestCert("Root", "Root", key.get(), /*is_ca=*/true);
4130 ASSERT_TRUE(root);
4131 ASSERT_TRUE(X509_sign(root.get(), key.get(), EVP_sha256()));
4132
4133 struct {
4134 std::vector<std::pair<int, std::string>> cert_subject;
4135 std::vector<std::string> cert_dns_names;
4136 std::vector<std::string> cert_emails;
4137 std::vector<std::string> valid_dns_names;
4138 std::vector<std::string> invalid_dns_names;
4139 std::vector<std::string> valid_emails;
4140 std::vector<std::string> invalid_emails;
4141 unsigned flags;
4142 } kTests[] = {
4143 // DNS names only match DNS names and do so case-insensitively.
4144 {
4145 /*cert_subject=*/{},
4146 /*cert_dns_names=*/{"example.com", "WWW.EXAMPLE.COM"},
4147 /*cert_emails=*/{},
4148 /*valid_dns_names=*/
4149 {"example.com", "EXAMPLE.COM", "www.example.com", "WWW.EXAMPLE.COM"},
4150 /*invalid_dns_names=*/{"test.example.com", "example.org"},
4151 /*valid_emails=*/{},
4152 /*invalid_emails=*/{"test@example.com", "example.com"},
4153 /*flags=*/0,
4154 },
4155
4156 // DNS wildcards match exactly one component.
4157 {
4158 /*cert_subject=*/{},
4159 /*cert_dns_names=*/{"*.example.com", "*.EXAMPLE.ORG"},
4160 /*cert_emails=*/{},
4161 /*valid_dns_names=*/
4162 {"www.example.com", "WWW.EXAMPLE.COM", "www.example.org",
4163 "WWW.EXAMPLE.ORG"},
4164 /*invalid_dns_names=*/{"example.com", "test.www.example.com"},
4165 /*valid_emails=*/{},
4166 /*invalid_emails=*/{"test@example.com", "www.example.com"},
4167 /*flags=*/0,
4168 },
4169
4170 // DNS wildcards can be disabled.
4171 // TODO(davidben): Can we remove this feature? Does anyone use it?
4172 {
4173 /*cert_subject=*/{},
4174 /*cert_dns_names=*/{"example.com", "*.example.com"},
4175 /*cert_emails=*/{},
4176 /*valid_dns_names=*/{"example.com"},
4177 /*invalid_dns_names=*/{"www.example.com"},
4178 /*valid_emails=*/{},
4179 /*invalid_emails=*/{},
4180 /*flags=*/X509_CHECK_FLAG_NO_WILDCARDS,
4181 },
4182
4183 // Invalid DNS wildcards do not match.
4184 {
4185 /*cert_subject=*/{},
4186 /*cert_dns_names=*/
4187 {"a.*", "**.b.example", "*c.example", "d*.example", "e*e.example",
4188 "*", ".", "..", "*."},
4189 /*cert_emails=*/{},
4190 /*valid_dns_names=*/{},
4191 /*invalid_dns_names=*/
4192 {"a.example", "test.b.example", "cc.example", "dd.example",
4193 "eee.example", "f", "g."},
4194 /*valid_emails=*/{},
4195 /*invalid_emails=*/{},
4196 /*flags=*/0,
4197 },
4198
4199 // IDNs match like any other DNS labels.
4200 {
4201 /*cert_subject=*/{},
4202 /*cert_dns_names=*/
4203 {"xn--rger-koa.a.example", "*.xn--rger-koa.b.example",
4204 "www.xn--rger-koa.c.example"},
4205 /*cert_emails=*/{},
4206 /*valid_dns_names=*/
4207 {"xn--rger-koa.a.example", "www.xn--rger-koa.b.example",
4208 "www.xn--rger-koa.c.example"},
4209 /*invalid_dns_names=*/
4210 {"www.xn--rger-koa.a.example", "xn--rger-koa.b.example",
4211 "www.xn--rger-koa.d.example"},
4212 /*valid_emails=*/{},
4213 /*invalid_emails=*/{},
4214 /*flags=*/0,
4215 },
4216
4217 // For now, DNS names are also extracted out of the common name, but only
4218 // there is no SAN list.
4219 // TODO(https://crbug.com/boringssl/464): Remove this.
4220 {
4221 /*cert_subject=*/{{NID_commonName, "a.example"},
4222 {NID_commonName, "*.b.example"}},
4223 /*cert_dns_names=*/{},
4224 /*cert_emails=*/{},
4225 /*valid_dns_names=*/
4226 {"a.example", "A.EXAMPLE", "test.b.example", "TEST.B.EXAMPLE"},
4227 /*invalid_dns_names=*/{},
4228 /*valid_emails=*/{},
4229 /*invalid_emails=*/{},
4230 /*flags=*/0,
4231 },
4232 {
4233 /*cert_subject=*/{{NID_commonName, "a.example"},
4234 {NID_commonName, "*.b.example"}},
4235 /*cert_dns_names=*/{"example.com"},
4236 /*cert_emails=*/{},
4237 /*valid_dns_names=*/{},
4238 /*invalid_dns_names=*/
4239 {"a.example", "A.EXAMPLE", "test.b.example", "TEST.B.EXAMPLE"},
4240 /*valid_emails=*/{},
4241 /*invalid_emails=*/{},
4242 /*flags=*/0,
4243 },
4244
4245 // Other subject RDNs do not provide DNS names.
4246 {
4247 /*cert_subject=*/{{NID_organizationName, "example.com"}},
4248 /*cert_dns_names=*/{},
4249 /*cert_emails=*/{},
4250 /*valid_dns_names=*/{},
4251 /*invalid_dns_names=*/{"example.com"},
4252 /*valid_emails=*/{},
4253 /*invalid_emails=*/{},
4254 /*flags=*/0,
4255 },
4256
4257 // Input DNS names cannot have wildcards.
4258 {
4259 /*cert_subject=*/{},
4260 /*cert_dns_names=*/{"www.example.com"},
4261 /*cert_emails=*/{},
4262 /*valid_dns_names=*/{},
4263 /*invalid_dns_names=*/{"*.example.com"},
4264 /*valid_emails=*/{},
4265 /*invalid_emails=*/{},
4266 /*flags=*/0,
4267 },
4268
David Benjamin9631bc12021-12-11 00:08:27 -05004269 // OpenSSL has some non-standard wildcard syntax for input DNS names. We
4270 // do not support this.
David Benjamin405c7882021-12-10 23:57:34 -05004271 {
4272 /*cert_subject=*/{},
4273 /*cert_dns_names=*/{"www.a.example", "*.b.test"},
4274 /*cert_emails=*/{},
David Benjamin9631bc12021-12-11 00:08:27 -05004275 /*valid_dns_names=*/{},
4276 /*invalid_dns_names=*/
4277 {".www.a.example", ".www.b.test", ".a.example", ".b.test", ".example",
4278 ".test"},
David Benjamin405c7882021-12-10 23:57:34 -05004279 /*valid_emails=*/{},
4280 /*invalid_emails=*/{},
4281 /*flags=*/0,
4282 },
4283
4284 // Emails match case-sensitively before the '@' and case-insensitively
4285 // after. They do not match DNS names.
4286 {
4287 /*cert_subject=*/{},
4288 /*cert_dns_names=*/{},
4289 /*cert_emails=*/{"test@a.example", "TEST@B.EXAMPLE"},
4290 /*valid_dns_names=*/{},
4291 /*invalid_dns_names=*/{"a.example", "b.example"},
4292 /*valid_emails=*/
4293 {"test@a.example", "test@A.EXAMPLE", "TEST@b.example",
4294 "TEST@B.EXAMPLE"},
4295 /*invalid_emails=*/
4296 {"TEST@a.example", "test@B.EXAMPLE", "another-test@a.example",
4297 "est@a.example"},
4298 /*flags=*/0,
4299 },
4300
4301 // Emails may also be found in the subject.
4302 {
4303 /*cert_subject=*/{{NID_pkcs9_emailAddress, "test@a.example"},
4304 {NID_pkcs9_emailAddress, "TEST@B.EXAMPLE"}},
4305 /*cert_dns_names=*/{},
4306 /*cert_emails=*/{},
4307 /*valid_dns_names=*/{},
4308 /*invalid_dns_names=*/{"a.example", "b.example"},
4309 /*valid_emails=*/
4310 {"test@a.example", "test@A.EXAMPLE", "TEST@b.example",
4311 "TEST@B.EXAMPLE"},
4312 /*invalid_emails=*/
4313 {"TEST@a.example", "test@B.EXAMPLE", "another-test@a.example",
4314 "est@a.example"},
4315 /*flags=*/0,
4316 },
4317
4318 // There are no email wildcard names.
4319 {
4320 /*cert_subject=*/{},
4321 /*cert_dns_names=*/{},
4322 /*cert_emails=*/{"test@*.a.example", "@b.example", "*@c.example"},
4323 /*valid_dns_names=*/{},
4324 /*invalid_dns_names=*/{},
4325 /*valid_emails=*/{},
4326 /*invalid_emails=*/
4327 {"test@test.a.example", "test@b.example", "test@c.example"},
4328 /*flags=*/0,
4329 },
4330
4331 // Unrelated RDNs can be skipped when looking in the subject.
4332 {
4333 /*cert_subject=*/{{NID_organizationName, "Acme Corporation"},
4334 {NID_commonName, "a.example"},
4335 {NID_pkcs9_emailAddress, "test@b.example"},
4336 {NID_countryName, "US"}},
4337 /*cert_dns_names=*/{},
4338 /*cert_emails=*/{},
4339 /*valid_dns_names=*/{"a.example"},
4340 /*invalid_dns_names=*/{},
4341 /*valid_emails=*/{"test@b.example"},
4342 /*invalid_emails=*/{},
4343 /*flags=*/0,
4344 },
4345 };
4346
4347 size_t i = 0;
4348 for (const auto &t : kTests) {
4349 SCOPED_TRACE(i++);
4350
4351 // Issue a test certificate.
4352 bssl::UniquePtr<X509> cert =
4353 MakeTestCert("Root", "Leaf", key.get(), /*is_ca=*/false);
4354 ASSERT_TRUE(cert);
4355 if (!t.cert_subject.empty()) {
4356 bssl::UniquePtr<X509_NAME> subject(X509_NAME_new());
4357 ASSERT_TRUE(subject);
4358 for (const auto &entry : t.cert_subject) {
4359 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
4360 subject.get(), entry.first, MBSTRING_ASC,
4361 reinterpret_cast<const unsigned char *>(entry.second.data()),
4362 entry.second.size(), /*loc=*/-1, /*set=*/0));
4363 }
4364 ASSERT_TRUE(X509_set_subject_name(cert.get(), subject.get()));
4365 }
4366 bssl::UniquePtr<GENERAL_NAMES> sans(sk_GENERAL_NAME_new_null());
4367 ASSERT_TRUE(sans);
4368 for (const auto &dns : t.cert_dns_names) {
4369 bssl::UniquePtr<GENERAL_NAME> name(GENERAL_NAME_new());
4370 ASSERT_TRUE(name);
4371 name->type = GEN_DNS;
4372 name->d.dNSName = ASN1_IA5STRING_new();
4373 ASSERT_TRUE(name->d.dNSName);
4374 ASSERT_TRUE(ASN1_STRING_set(name->d.dNSName, dns.data(), dns.size()));
4375 ASSERT_TRUE(bssl::PushToStack(sans.get(), std::move(name)));
4376 }
4377 for (const auto &email : t.cert_emails) {
4378 bssl::UniquePtr<GENERAL_NAME> name(GENERAL_NAME_new());
4379 ASSERT_TRUE(name);
4380 name->type = GEN_EMAIL;
4381 name->d.rfc822Name = ASN1_IA5STRING_new();
4382 ASSERT_TRUE(name->d.rfc822Name);
4383 ASSERT_TRUE(
4384 ASN1_STRING_set(name->d.rfc822Name, email.data(), email.size()));
4385 ASSERT_TRUE(bssl::PushToStack(sans.get(), std::move(name)));
4386 }
4387 if (sk_GENERAL_NAME_num(sans.get()) != 0) {
4388 ASSERT_TRUE(X509_add1_ext_i2d(cert.get(), NID_subject_alt_name,
4389 sans.get(), /*crit=*/0, /*flags=*/0));
4390 }
4391 ASSERT_TRUE(X509_sign(cert.get(), key.get(), EVP_sha256()));
4392
4393 for (const auto &dns : t.valid_dns_names) {
4394 SCOPED_TRACE(dns);
4395 EXPECT_EQ(1, X509_check_host(cert.get(), dns.data(), dns.size(), t.flags,
4396 /*peername=*/nullptr));
4397 EXPECT_EQ(X509_V_OK,
4398 Verify(cert.get(), {root.get()}, /*intermediates=*/{},
4399 /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
4400 ASSERT_TRUE(X509_VERIFY_PARAM_set1_host(
4401 param, dns.data(), dns.size()));
4402 X509_VERIFY_PARAM_set_hostflags(param, t.flags);
4403 }));
4404 }
4405
4406 for (const auto &dns : t.invalid_dns_names) {
4407 SCOPED_TRACE(dns);
4408 EXPECT_EQ(0, X509_check_host(cert.get(), dns.data(), dns.size(), t.flags,
4409 /*peername=*/nullptr));
4410 EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
4411 Verify(cert.get(), {root.get()}, /*intermediates=*/{},
4412 /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
4413 ASSERT_TRUE(X509_VERIFY_PARAM_set1_host(
4414 param, dns.data(), dns.size()));
4415 X509_VERIFY_PARAM_set_hostflags(param, t.flags);
4416 }));
4417 }
4418
4419 for (const auto &email : t.valid_emails) {
4420 SCOPED_TRACE(email);
4421 EXPECT_EQ(
4422 1, X509_check_email(cert.get(), email.data(), email.size(), t.flags));
4423 EXPECT_EQ(X509_V_OK,
4424 Verify(cert.get(), {root.get()}, /*intermediates=*/{},
4425 /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
4426 ASSERT_TRUE(X509_VERIFY_PARAM_set1_email(
4427 param, email.data(), email.size()));
4428 X509_VERIFY_PARAM_set_hostflags(param, t.flags);
4429 }));
4430 }
4431
4432 for (const auto &email : t.invalid_emails) {
4433 SCOPED_TRACE(email);
4434 EXPECT_EQ(
4435 0, X509_check_email(cert.get(), email.data(), email.size(), t.flags));
4436 EXPECT_EQ(X509_V_ERR_EMAIL_MISMATCH,
4437 Verify(cert.get(), {root.get()}, /*intermediates=*/{},
4438 /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
4439 ASSERT_TRUE(X509_VERIFY_PARAM_set1_email(
4440 param, email.data(), email.size()));
4441 X509_VERIFY_PARAM_set_hostflags(param, t.flags);
4442 }));
4443 }
4444 }
4445}
Adam Langleyf7975702022-01-12 16:23:11 -08004446
4447TEST(X509Test, AddDuplicates) {
4448 bssl::UniquePtr<X509_STORE> store(X509_STORE_new());
4449 bssl::UniquePtr<X509> a(CertFromPEM(kCrossSigningRootPEM));
4450 bssl::UniquePtr<X509> b(CertFromPEM(kRootCAPEM));
4451
4452 ASSERT_TRUE(store);
4453 ASSERT_TRUE(a);
4454 ASSERT_TRUE(b);
4455
4456 EXPECT_TRUE(X509_STORE_add_cert(store.get(), a.get()));
4457 EXPECT_TRUE(X509_STORE_add_cert(store.get(), b.get()));
4458 EXPECT_TRUE(X509_STORE_add_cert(store.get(), a.get()));
4459 EXPECT_TRUE(X509_STORE_add_cert(store.get(), b.get()));
4460 EXPECT_TRUE(X509_STORE_add_cert(store.get(), a.get()));
4461 EXPECT_TRUE(X509_STORE_add_cert(store.get(), b.get()));
4462
4463 EXPECT_EQ(sk_X509_OBJECT_num(X509_STORE_get0_objects(store.get())), 2u);
4464}
David Benjamine4b3e6a2022-02-21 00:13:17 -05004465
4466TEST(X509Test, BytesToHex) {
4467 struct {
4468 std::vector<uint8_t> bytes;
4469 const char *hex;
4470 } kTests[] = {
4471 {{}, ""},
4472 {{0x00}, "00"},
4473 {{0x00, 0x11, 0x22}, "00:11:22"},
4474 {{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
4475 "01:23:45:67:89:AB:CD:EF"},
4476 };
4477 for (const auto &t : kTests) {
4478 SCOPED_TRACE(Bytes(t.bytes));
4479 bssl::UniquePtr<char> hex(
4480 x509v3_bytes_to_hex(t.bytes.data(), t.bytes.size()));
4481 ASSERT_TRUE(hex);
4482 EXPECT_STREQ(hex.get(), t.hex);
4483 }
4484}
David Benjamindf6311b2022-04-15 11:11:22 +02004485
4486TEST(X509Test, NamePrint) {
4487 // kTestName is a DER-encoded X.509 that covers many cases.
4488 //
4489 // SEQUENCE {
4490 // SET {
4491 // SEQUENCE {
4492 // # countryName
4493 // OBJECT_IDENTIFIER { 2.5.4.6 }
4494 // PrintableString { "US" }
4495 // }
4496 // }
4497 // # Sets may be multi-valued, with different attributes. Try to keep this
4498 // # in DER set order, in case we ever enforce this in the parser.
4499 // SET {
4500 // SEQUENCE {
4501 // # stateOrProvinceName
4502 // OBJECT_IDENTIFIER { 2.5.4.8 }
4503 // PrintableString { "Some State" }
4504 // }
4505 // SEQUENCE {
4506 // # stateOrProvinceName
4507 // OBJECT_IDENTIFIER { 2.5.4.8 }
4508 // UTF8String { "Some Other State \xe2\x98\x83" }
4509 // }
4510 // SEQUENCE {
4511 // # stateOrProvinceName
4512 // OBJECT_IDENTIFIER { 2.5.4.8 }
4513 // BMPString { u"Another State \u2603" }
4514 // }
4515 // SEQUENCE {
4516 // # A custom OID
4517 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2 }
4518 // UniversalString { U"\u2603" }
4519 // }
4520 // }
4521 // # Custom OIDs may have non-string values.
4522 // SET {
4523 // SEQUENCE {
4524 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.3 }
4525 // SEQUENCE { INTEGER { 1 } INTEGER { 2 } }
4526 // }
4527 // }
4528 // SET {
4529 // SEQUENCE {
4530 // # organizationName
4531 // OBJECT_IDENTIFIER { 2.5.4.10 }
4532 // PrintableString { "Org Name" }
4533 // }
4534 // }
4535 // SET {
4536 // SEQUENCE {
4537 // # commonName
4538 // OBJECT_IDENTIFIER { 2.5.4.3 }
4539 // # Embed common delimiter forms to test how well they get escaped.
4540 // UTF8String { "Common
4541 // Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\nCN=A\n" }
4542 // }
4543 // }
4544 // SET {
4545 // SEQUENCE {
4546 // # commonName
4547 // OBJECT_IDENTIFIER { 2.5.4.3 }
4548 // # Test escaping of leading and trailing spaces.
4549 // UTF8String { " spaces " }
4550 // }
4551 // }
4552 static const uint8_t kTestName[] = {
4553 0x30, 0x82, 0x01, 0x00, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
4554 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x6d, 0x30, 0x11, 0x06, 0x03, 0x55,
4555 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61,
4556 0x74, 0x65, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x14, 0x53,
4557 0x6f, 0x6d, 0x65, 0x20, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x53, 0x74,
4558 0x61, 0x74, 0x65, 0x20, 0xe2, 0x98, 0x83, 0x30, 0x25, 0x06, 0x03, 0x55,
4559 0x04, 0x08, 0x1e, 0x1e, 0x00, 0x41, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74,
4560 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74,
4561 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x26, 0x03, 0x30, 0x14,
4562 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
4563 0x09, 0x02, 0x1c, 0x04, 0x00, 0x00, 0x26, 0x03, 0x31, 0x18, 0x30, 0x16,
4564 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
4565 0x09, 0x03, 0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x31, 0x11,
4566 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x4f, 0x72, 0x67,
4567 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55,
4568 0x04, 0x03, 0x0c, 0x39, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x4e,
4569 0x61, 0x6d, 0x65, 0x2f, 0x43, 0x4e, 0x3d, 0x41, 0x2f, 0x43, 0x4e, 0x3d,
4570 0x42, 0x2c, 0x43, 0x4e, 0x3d, 0x41, 0x2c, 0x43, 0x4e, 0x3d, 0x42, 0x2b,
4571 0x43, 0x4e, 0x3d, 0x41, 0x2b, 0x43, 0x4e, 0x3d, 0x42, 0x3b, 0x43, 0x4e,
4572 0x3d, 0x41, 0x3b, 0x43, 0x4e, 0x3d, 0x42, 0x0a, 0x43, 0x4e, 0x3d, 0x41,
4573 0x0a, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
4574 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x20};
4575
4576 const uint8_t *ptr = kTestName;
4577 bssl::UniquePtr<X509_NAME> name(
4578 d2i_X509_NAME(nullptr, &ptr, sizeof(kTestName)));
4579 ASSERT_TRUE(name);
4580 EXPECT_EQ(ptr, kTestName + sizeof(kTestName));
4581
4582 struct {
4583 int indent;
4584 unsigned long flags;
4585 std::string printed;
4586 } kTests[] = {
4587 // RFC 2253 uses , and + separators and encodes the RDNs in reverse.
4588 // OpenSSL's implementation additionally happens to reverse the values
4589 // within each RDN. RFC 2253 says any order is permissible.
4590 {/*indent=*/0,
4591 /*flags=*/XN_FLAG_RFC2253,
4592 "CN=\\ spaces\\ ,"
4593 "CN=Common "
4594 "Name/CN=A/CN=B\\,CN=A\\,CN=B\\+CN=A\\+CN=B\\;CN=A\\;CN=B\\0ACN=A\\0A,"
4595 "O=Org Name,"
4596 "1.2.840.113554.4.1.72585.3=#3006020101020102,"
4597 "1.2.840.113554.4.1.72585.2=#1C0400002603+"
4598 "ST=Another State \\E2\\98\\83+"
4599 "ST=Some Other State \\E2\\98\\83+"
4600 "ST=Some State,"
4601 "C=US"},
4602 {/*indent=*/2,
4603 /*flags=*/XN_FLAG_RFC2253,
4604 " "
4605 "CN=\\ spaces\\ ,"
4606 "CN=Common "
4607 "Name/CN=A/CN=B\\,CN=A\\,CN=B\\+CN=A\\+CN=B\\;CN=A\\;CN=B\\0ACN=A\\0A,"
4608 "O=Org Name,"
4609 "1.2.840.113554.4.1.72585.3=#3006020101020102,"
4610 "1.2.840.113554.4.1.72585.2=#1C0400002603+"
4611 "ST=Another State \\E2\\98\\83+"
4612 "ST=Some Other State \\E2\\98\\83+"
4613 "ST=Some State,"
4614 "C=US"},
4615 // |XN_FLAG_ONELINE| is an OpenSSL-specific single-line format. It also
4616 // omits |XN_FLAG_DUMP_UNKNOWN_FIELDS|, so unknown OIDs that use known
4617 // string types will still be decoded. (This may drop important
4618 // information if the unknown OID distinguishes between string types.) It
4619 // also passes |ASN1_STRFLGS_ESC_QUOTE|.
4620 {/*indent=*/0,
4621 /*flags=*/XN_FLAG_ONELINE,
4622 "C = US, "
4623 "ST = Some State + "
4624 "ST = Some Other State \\E2\\98\\83 + "
4625 "ST = Another State \\E2\\98\\83 + "
4626 "1.2.840.113554.4.1.72585.2 = \\E2\\98\\83, "
4627 "1.2.840.113554.4.1.72585.3 = #3006020101020102, "
4628 "O = Org Name, "
4629 "CN = \"Common "
4630 "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\", "
4631 "CN = \" spaces \""},
4632 // |XN_FLAG_MULTILINE| is an OpenSSL-specific multi-line format that tries
4633 // to vertically align the equal sizes. The vertical alignment doesn't
4634 // quite handle multi-valued RDNs right and uses a non-RFC-2253 escaping.
4635 {/*indent=*/0,
4636 /*flags=*/XN_FLAG_MULTILINE,
4637 "countryName = US\n"
4638 "stateOrProvinceName = Some State + "
4639 "stateOrProvinceName = Some Other State \\U2603 + "
4640 "stateOrProvinceName = Another State \\U2603 + "
4641 "1.2.840.113554.4.1.72585.2 = \\U2603\n"
4642 "1.2.840.113554.4.1.72585.3 = 0\\06\\02\\01\\01\\02\\01\\02\n"
4643 "organizationName = Org Name\n"
4644 "commonName = Common "
4645 "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\n"
4646 "commonName = spaces "},
4647 // The multiline format indents every line.
4648 {/*indent=*/2,
4649 /*flags=*/XN_FLAG_MULTILINE,
4650 " countryName = US\n"
4651 " stateOrProvinceName = Some State + "
4652 "stateOrProvinceName = Some Other State \\U2603 + "
4653 "stateOrProvinceName = Another State \\U2603 + "
4654 "1.2.840.113554.4.1.72585.2 = \\U2603\n"
4655 " 1.2.840.113554.4.1.72585.3 = 0\\06\\02\\01\\01\\02\\01\\02\n"
4656 " organizationName = Org Name\n"
4657 " commonName = Common "
4658 "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\n"
4659 " commonName = spaces "},
4660 // Callers can also customize the output, wuith both |XN_FLAG_*| and
4661 // |ASN1_STRFLGS_*|. |XN_FLAG_SEP_SPLUS_SPC| uses semicolon separators and
4662 // |XN_FLAG_FN_OID| forces OIDs.
4663 {/*indent=*/0,
4664 /*flags=*/XN_FLAG_SEP_SPLUS_SPC | XN_FLAG_FN_OID | ASN1_STRFLGS_RFC2253 |
4665 ASN1_STRFLGS_ESC_QUOTE,
4666 "2.5.4.6=US; "
4667 "2.5.4.8=Some State + "
4668 "2.5.4.8=Some Other State \\E2\\98\\83 + "
4669 "2.5.4.8=Another State \\E2\\98\\83 + "
4670 "1.2.840.113554.4.1.72585.2=\\E2\\98\\83; "
4671 "1.2.840.113554.4.1.72585.3=#3006020101020102; "
4672 "2.5.4.10=Org Name; "
4673 "2.5.4.3=\"Common "
4674 "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\"; "
4675 "2.5.4.3=\" spaces \""},
4676 // |XN_FLAG_COMPAT| matches |X509_NAME_print|, rather than
4677 // |X509_NAME_print_ex|.
4678 //
4679 // TODO(davidben): This works by post-processing the output of
4680 // |X509_NAME_oneline|, which uses "/"" separators, and replacing with
4681 // ", ". The escaping is ambiguous and the post-processing is buggy, so
4682 // some of the trailing slashes are still present and some internal
4683 // slashes are mis-converted.
4684 {/*indent=*/0,
4685 /*flags=*/XN_FLAG_COMPAT,
4686 "C=US, "
4687 "ST=Some State, "
4688 "ST=Some Other State \\xE2\\x98\\x83, "
4689 "ST=\\x00A\\x00n\\x00o\\x00t\\x00h\\x00e\\x00r\\x00 "
4690 "\\x00S\\x00t\\x00a\\x00t\\x00e\\x00 &\\x03/"
4691 "1.2.840.113554.4.1.72585.2=\\x00\\x00&\\x03/"
4692 "1.2.840.113554.4.1.72585.3=0\\x06\\x02\\x01\\x01\\x02\\x01\\x02, "
4693 "O=Org Name, "
4694 "CN=Common Name, "
4695 "CN=A, CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\x0ACN=A\\x0A, "
4696 "CN= spaces "},
4697 };
4698 for (const auto &t : kTests) {
4699 SCOPED_TRACE(t.printed);
4700 bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
4701 ASSERT_TRUE(bio);
4702 int len = X509_NAME_print_ex(bio.get(), name.get(), t.indent, t.flags);
4703 ASSERT_GT(len, 0);
4704
4705 const uint8_t *printed;
4706 size_t printed_len;
4707 ASSERT_TRUE(BIO_mem_contents(bio.get(), &printed, &printed_len));
4708 EXPECT_EQ(std::string(printed, printed + printed_len), t.printed);
4709 if (t.flags != XN_FLAG_COMPAT) {
4710 // TODO(davidben): |XN_FLAG_COMPAT| does not return the length.
4711 EXPECT_EQ(static_cast<size_t>(len), printed_len);
4712
4713 // Passing a null |BIO| measures the output instead.
4714 len = X509_NAME_print_ex(nullptr, name.get(), t.indent, t.flags);
4715 EXPECT_GT(len, 0);
4716 EXPECT_EQ(static_cast<size_t>(len), printed_len);
4717 }
4718 }
4719
4720 // TODO(davidben): This escapes the underlying bytes in the string, but that
4721 // is ambiguous without capturing the type. Should this escape like
4722 // |ASN1_STRFLGS_UTF8_CONVERT| instead?
4723 static const char *kOnelineComponents[] = {
4724 "/C=US",
4725 "/ST=Some State",
4726 "/ST=Some Other State \\xE2\\x98\\x83",
David Benjamin7d1fc2b2022-10-14 08:44:15 -04004727 ("/ST=\\x00A\\x00n\\x00o\\x00t\\x00h\\x00e\\x00r\\x00 "
4728 "\\x00S\\x00t\\x00a\\x00t\\x00e\\x00 &\\x03"),
David Benjamindf6311b2022-04-15 11:11:22 +02004729 "/1.2.840.113554.4.1.72585.2=\\x00\\x00&\\x03",
4730 "/1.2.840.113554.4.1.72585.3=0\\x06\\x02\\x01\\x01\\x02\\x01\\x02",
4731 "/O=Org Name",
4732 "/CN=Common Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\x0ACN=A\\x0A",
4733 "/CN= spaces ",
4734 };
4735 std::string oneline_expected;
4736 for (const auto& component : kOnelineComponents) {
4737 oneline_expected += component;
4738 }
4739
4740 // Given null buffer, |X509_NAME_oneline| allocates a new output.
4741 bssl::UniquePtr<char> oneline(X509_NAME_oneline(name.get(), nullptr, 0));
4742 ASSERT_TRUE(oneline);
4743 EXPECT_EQ(oneline.get(), oneline_expected);
4744
4745 // Otherwise it writes to the specified buffer. Note one extra byte is needed
4746 // for the trailing NUL.
4747 char buf[1024];
4748 ASSERT_GE(sizeof(buf), oneline_expected.size() + 2);
4749 ASSERT_EQ(buf,
4750 X509_NAME_oneline(name.get(), buf, oneline_expected.size() + 1));
4751 EXPECT_EQ(buf, oneline_expected);
4752
4753 memset(buf, 'a', sizeof(buf));
4754 ASSERT_EQ(buf,
4755 X509_NAME_oneline(name.get(), buf, oneline_expected.size() + 2));
4756 EXPECT_EQ(buf, oneline_expected);
4757
4758 // If the length is too small, |X509_NAME_oneline| truncates at name
4759 // entry boundaries.
4760 EXPECT_EQ(nullptr, X509_NAME_oneline(name.get(), buf, 0));
4761 for (size_t len = 1; len < oneline_expected.size(); len++) {
4762 SCOPED_TRACE(len);
4763 memset(buf, 'a', sizeof(buf));
4764 EXPECT_EQ(buf, X509_NAME_oneline(name.get(), buf, len));
4765
4766 std::string truncated;
4767 for (const auto& component : kOnelineComponents) {
4768 if (truncated.size() + strlen(component) + 1 > len) {
4769 break;
4770 }
4771 truncated += component;
4772 }
4773 EXPECT_EQ(buf, truncated);
4774 }
4775}
David Benjamin16946272022-05-20 13:04:56 -04004776
4777// kLargeSerialPEM is a certificate with a large serial number.
4778static const char kLargeSerialPEM[] = R"(
4779-----BEGIN CERTIFICATE-----
4780MIICZjCCAc+gAwIBAgIQASNFZ4mrze8BI0VniavN7zANBgkqhkiG9w0BAQsFADA2
4781MRowGAYDVQQKExFCb3JpbmdTU0wgVEVTVElORzEYMBYGA1UEAxMPSW50ZXJtZWRp
4782YXRlIENBMCAXDTE1MDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAyMRowGAYD
4783VQQKExFCb3JpbmdTU0wgVEVTVElORzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wgZ8w
4784DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMPRTRliCpKEnug6OzI0rJVcQep5p+aT
47859sCg+pj+HVyg/DYTwqZ6qJRKhM+MbkhdJuU7FyqlsBeCeM/OjwMjcY0yEB/xJg1i
4786ygfuBztTLuPnHxtSuKwae5MeqSofp3j97sRMnuLcKlHxu8rXoOCAS9BO50uKnPwU
4787Ee1iEVqR92FPAgMBAAGjdzB1MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggr
4788BgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAZBgNVHQ4EEgQQo3mm9u6v
4789uaVeN4wRgDTidTAbBgNVHSMEFDASgBCMGmiotXbbXVd7H40UsgajMA0GCSqGSIb3
4790DQEBCwUAA4GBAGP+n4kKGn/8uddYLWTXbUsz+KLuEXNDMyu3vRufLjTpIbP2MCNo
479185fhLeC3fzKuGOk+6QGVLOBBcWDrrLqrmqnWdBMPULDo2QoF71a4GVjeJh+ax/tZ
4792PyeGVPUK21TE0LDIxf2a11d1CJw582MgZQIPk4tXk+AcU9EqIceKgECG
4793-----END CERTIFICATE-----
4794)";
4795
4796TEST(X509Test, Print) {
4797 bssl::UniquePtr<X509> cert(CertFromPEM(kLargeSerialPEM));
4798 ASSERT_TRUE(cert);
4799
4800 bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
4801 ASSERT_TRUE(bio);
4802 EXPECT_TRUE(X509_print_ex(bio.get(), cert.get(), 0, 0));
4803 // Nothing should be left in the error queue.
4804 EXPECT_EQ(0u, ERR_peek_error());
4805
4806 // This output is not guaranteed to be stable, but we assert on it to make
4807 // sure something is printed.
4808 const uint8_t *data;
4809 size_t data_len;
4810 ASSERT_TRUE(BIO_mem_contents(bio.get(), &data, &data_len));
4811 std::string print(reinterpret_cast<const char*>(data), data_len);
4812 EXPECT_EQ(print, R"(Certificate:
4813 Data:
4814 Version: 3 (0x2)
4815 Serial Number:
4816 01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef
4817 Signature Algorithm: sha256WithRSAEncryption
4818 Issuer: O=BoringSSL TESTING, CN=Intermediate CA
4819 Validity
4820 Not Before: Jan 1 00:00:00 2015 GMT
4821 Not After : Jan 1 00:00:00 2100 GMT
4822 Subject: O=BoringSSL TESTING, CN=example.com
4823 Subject Public Key Info:
4824 Public Key Algorithm: rsaEncryption
4825 Public-Key: (1024 bit)
4826 Modulus:
4827 00:c3:d1:4d:19:62:0a:92:84:9e:e8:3a:3b:32:34:
4828 ac:95:5c:41:ea:79:a7:e6:93:f6:c0:a0:fa:98:fe:
4829 1d:5c:a0:fc:36:13:c2:a6:7a:a8:94:4a:84:cf:8c:
4830 6e:48:5d:26:e5:3b:17:2a:a5:b0:17:82:78:cf:ce:
4831 8f:03:23:71:8d:32:10:1f:f1:26:0d:62:ca:07:ee:
4832 07:3b:53:2e:e3:e7:1f:1b:52:b8:ac:1a:7b:93:1e:
4833 a9:2a:1f:a7:78:fd:ee:c4:4c:9e:e2:dc:2a:51:f1:
4834 bb:ca:d7:a0:e0:80:4b:d0:4e:e7:4b:8a:9c:fc:14:
4835 11:ed:62:11:5a:91:f7:61:4f
4836 Exponent: 65537 (0x10001)
4837 X509v3 extensions:
4838 X509v3 Key Usage: critical
4839 Digital Signature, Key Encipherment
4840 X509v3 Extended Key Usage:
4841 TLS Web Server Authentication, TLS Web Client Authentication
4842 X509v3 Basic Constraints: critical
4843 CA:FALSE
4844 X509v3 Subject Key Identifier:
4845 A3:79:A6:F6:EE:AF:B9:A5:5E:37:8C:11:80:34:E2:75
4846 X509v3 Authority Key Identifier:
4847 keyid:8C:1A:68:A8:B5:76:DB:5D:57:7B:1F:8D:14:B2:06:A3
4848
4849 Signature Algorithm: sha256WithRSAEncryption
4850 63:fe:9f:89:0a:1a:7f:fc:b9:d7:58:2d:64:d7:6d:4b:33:f8:
4851 a2:ee:11:73:43:33:2b:b7:bd:1b:9f:2e:34:e9:21:b3:f6:30:
4852 23:68:f3:97:e1:2d:e0:b7:7f:32:ae:18:e9:3e:e9:01:95:2c:
4853 e0:41:71:60:eb:ac:ba:ab:9a:a9:d6:74:13:0f:50:b0:e8:d9:
4854 0a:05:ef:56:b8:19:58:de:26:1f:9a:c7:fb:59:3f:27:86:54:
4855 f5:0a:db:54:c4:d0:b0:c8:c5:fd:9a:d7:57:75:08:9c:39:f3:
4856 63:20:65:02:0f:93:8b:57:93:e0:1c:53:d1:2a:21:c7:8a:80:
4857 40:86
4858)");
4859}
David Benjamin7528f032022-07-08 15:43:46 -04004860
4861TEST(X509Test, AddExt) {
4862 bssl::UniquePtr<X509> x509(X509_new());
4863 ASSERT_TRUE(x509);
4864
4865 struct Extension {
4866 int nid;
4867 bool critical;
4868 std::vector<uint8_t> data;
4869 };
4870 auto expect_extensions = [&](const std::vector<Extension> &exts) {
4871 ASSERT_EQ(static_cast<size_t>(X509_get_ext_count(x509.get())), exts.size());
4872 for (size_t i = 0; i < exts.size(); i++) {
4873 SCOPED_TRACE(i);
David Benjamin09b8fd42022-07-10 19:14:48 -04004874 const X509_EXTENSION *ext = X509_get_ext(x509.get(), static_cast<int>(i));
David Benjamin7528f032022-07-08 15:43:46 -04004875 EXPECT_EQ(OBJ_obj2nid(X509_EXTENSION_get_object(ext)), exts[i].nid);
4876 EXPECT_EQ(X509_EXTENSION_get_critical(ext), exts[i].critical ? 1 : 0);
David Benjamin09b8fd42022-07-10 19:14:48 -04004877 const ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(ext);
David Benjamin7528f032022-07-08 15:43:46 -04004878 EXPECT_EQ(Bytes(ASN1_STRING_get0_data(data), ASN1_STRING_length(data)),
4879 Bytes(exts[i].data));
4880 }
4881 };
4882
4883 // Make a few sample extensions.
4884
4885 // SEQUENCE {}
4886 std::vector<uint8_t> basic1_der = {0x30, 0x00};
4887 const uint8_t *inp = basic1_der.data();
4888 bssl::UniquePtr<BASIC_CONSTRAINTS> basic1_obj(
4889 d2i_BASIC_CONSTRAINTS(nullptr, &inp, basic1_der.size()));
4890 EXPECT_EQ(inp, basic1_der.data() + basic1_der.size());
4891
4892 // SEQUENCE { BOOLEAN { TRUE } }
4893 std::vector<uint8_t> basic2_der = {0x30, 0x03, 0x01, 0x01, 0xff};
4894 inp = basic2_der.data();
4895 bssl::UniquePtr<BASIC_CONSTRAINTS> basic2_obj(
4896 d2i_BASIC_CONSTRAINTS(nullptr, &inp, basic2_der.size()));
4897 EXPECT_EQ(inp, basic2_der.data() + basic2_der.size());
4898
4899 // OCTET_STRING {}
4900 std::vector<uint8_t> skid1_der = {0x04, 0x00};
4901 inp = skid1_der.data();
4902 bssl::UniquePtr<ASN1_OCTET_STRING> skid1_obj(
4903 d2i_ASN1_OCTET_STRING(nullptr, &inp, skid1_der.size()));
4904 EXPECT_EQ(inp, skid1_der.data() + skid1_der.size());
4905
4906 // OCTET_STRING { "a" }
4907 std::vector<uint8_t> skid2_der = {0x04, 0x01, 0x61};
4908 inp = skid2_der.data();
4909 bssl::UniquePtr<ASN1_OCTET_STRING> skid2_obj(
4910 d2i_ASN1_OCTET_STRING(nullptr, &inp, skid2_der.size()));
4911 EXPECT_EQ(inp, skid2_der.data() + skid2_der.size());
4912
4913 // Initially, the extension list is empty.
4914 expect_extensions({});
4915
4916 // Adding extensions works with the default settings.
4917 EXPECT_EQ(
4918 1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic1_obj.get(),
4919 /*crit=*/1, X509V3_ADD_DEFAULT));
4920 expect_extensions({{NID_basic_constraints, true, basic1_der}});
4921 EXPECT_EQ(1, X509_add1_ext_i2d(x509.get(), NID_subject_key_identifier,
4922 skid1_obj.get(),
4923 /*crit=*/0, X509V3_ADD_DEFAULT));
4924 expect_extensions({{NID_basic_constraints, true, basic1_der},
4925 {NID_subject_key_identifier, false, skid1_der}});
4926
4927 // By default, we cannot add duplicates.
4928 EXPECT_EQ(
4929 0, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic2_obj.get(),
4930 /*crit=*/0, X509V3_ADD_DEFAULT));
4931 expect_extensions({{NID_basic_constraints, true, basic1_der},
4932 {NID_subject_key_identifier, false, skid1_der}});
4933
4934 // |X509V3_ADD_KEEP_EXISTING| silently keeps the existing extension if already
4935 // present.
4936 EXPECT_EQ(
4937 1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic2_obj.get(),
4938 /*crit=*/0, X509V3_ADD_KEEP_EXISTING));
4939 expect_extensions({{NID_basic_constraints, true, basic1_der},
4940 {NID_subject_key_identifier, false, skid1_der}});
4941
4942 // |X509V3_ADD_REPLACE| replaces it.
4943 EXPECT_EQ(
4944 1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic2_obj.get(),
4945 /*crit=*/0, X509V3_ADD_REPLACE));
4946 expect_extensions({{NID_basic_constraints, false, basic2_der},
4947 {NID_subject_key_identifier, false, skid1_der}});
4948
4949 // |X509V3_ADD_REPLACE_EXISTING| also replaces matches.
4950 EXPECT_EQ(1, X509_add1_ext_i2d(x509.get(), NID_subject_key_identifier,
4951 skid2_obj.get(),
4952 /*crit=*/1, X509V3_ADD_REPLACE_EXISTING));
4953 expect_extensions({{NID_basic_constraints, false, basic2_der},
4954 {NID_subject_key_identifier, true, skid2_der}});
4955
4956 // |X509V3_ADD_DELETE| ignores the value and deletes the extension.
4957 EXPECT_EQ(1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, nullptr, 0,
4958 X509V3_ADD_DELETE));
4959 expect_extensions({{NID_subject_key_identifier, true, skid2_der}});
4960
4961 // Not finding an extension to delete is an error.
4962 EXPECT_EQ(0, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, nullptr, 0,
4963 X509V3_ADD_DELETE));
4964 expect_extensions({{NID_subject_key_identifier, true, skid2_der}});
4965
4966 // |X509V3_ADD_REPLACE_EXISTING| fails if it cannot find a match.
4967 EXPECT_EQ(
4968 0, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic1_obj.get(),
4969 /*crit=*/1, X509V3_ADD_REPLACE_EXISTING));
4970 expect_extensions({{NID_subject_key_identifier, true, skid2_der}});
4971
4972 // |X509V3_ADD_REPLACE| adds a new extension if not preseent.
4973 EXPECT_EQ(
4974 1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic1_obj.get(),
4975 /*crit=*/1, X509V3_ADD_REPLACE));
4976 expect_extensions({{NID_subject_key_identifier, true, skid2_der},
4977 {NID_basic_constraints, true, basic1_der}});
4978
4979 // Delete the extension again.
4980 EXPECT_EQ(1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, nullptr, 0,
4981 X509V3_ADD_DELETE));
4982 expect_extensions({{NID_subject_key_identifier, true, skid2_der}});
4983
4984 // |X509V3_ADD_KEEP_EXISTING| adds a new extension if not preseent.
4985 EXPECT_EQ(
4986 1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic1_obj.get(),
4987 /*crit=*/1, X509V3_ADD_KEEP_EXISTING));
4988 expect_extensions({{NID_subject_key_identifier, true, skid2_der},
4989 {NID_basic_constraints, true, basic1_der}});
4990
4991 // Delete the extension again.
4992 EXPECT_EQ(1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, nullptr, 0,
4993 X509V3_ADD_DELETE));
4994 expect_extensions({{NID_subject_key_identifier, true, skid2_der}});
4995
4996 // |X509V3_ADD_APPEND| adds a new extension if not present.
4997 EXPECT_EQ(
4998 1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic1_obj.get(),
4999 /*crit=*/1, X509V3_ADD_APPEND));
5000 expect_extensions({{NID_subject_key_identifier, true, skid2_der},
5001 {NID_basic_constraints, true, basic1_der}});
5002
5003 // |X509V3_ADD_APPEND| keeps adding duplicates (invalid) even if present.
5004 EXPECT_EQ(
5005 1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, basic2_obj.get(),
5006 /*crit=*/0, X509V3_ADD_APPEND));
5007 expect_extensions({{NID_subject_key_identifier, true, skid2_der},
5008 {NID_basic_constraints, true, basic1_der},
5009 {NID_basic_constraints, false, basic2_der}});
5010
5011 // |X509V3_ADD_DELETE| only deletes one extension at a time.
5012 EXPECT_EQ(1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, nullptr, 0,
5013 X509V3_ADD_DELETE));
5014 expect_extensions({{NID_subject_key_identifier, true, skid2_der},
5015 {NID_basic_constraints, false, basic2_der}});
5016 EXPECT_EQ(1, X509_add1_ext_i2d(x509.get(), NID_basic_constraints, nullptr, 0,
5017 X509V3_ADD_DELETE));
5018 expect_extensions({{NID_subject_key_identifier, true, skid2_der}});
5019}
David Benjamin3be30a52022-07-09 14:47:13 -04005020
5021TEST(X509Test, NameEntry) {
5022 bssl::UniquePtr<X509_NAME> name(X509_NAME_new());
5023 ASSERT_TRUE(name);
5024
5025 auto check_name = [&](const char *expected_rfc2253) {
5026 // Check RDN indices are self-consistent.
5027 int num = X509_NAME_entry_count(name.get());
5028 if (num > 0) {
5029 // RDN indices must start at zero.
5030 EXPECT_EQ(0, X509_NAME_ENTRY_set(X509_NAME_get_entry(name.get(), 0)));
5031 }
5032 for (int i = 1; i < num; i++) {
5033 int prev = X509_NAME_ENTRY_set(X509_NAME_get_entry(name.get(), i - 1));
5034 int current = X509_NAME_ENTRY_set(X509_NAME_get_entry(name.get(), i));
5035 // RDN indices must increase consecutively.
5036 EXPECT_TRUE(prev == current || prev + 1 == current)
5037 << "Entry " << i << " has RDN index " << current
5038 << " which is inconsistent with previous index " << prev;
5039 }
5040
5041 // Check the name based on the RFC 2253 serialization. Note the RFC 2253
5042 // serialization is in reverse.
5043 bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
5044 ASSERT_TRUE(bio);
5045 EXPECT_GE(X509_NAME_print_ex(bio.get(), name.get(), 0, XN_FLAG_RFC2253), 0);
5046 const uint8_t *data;
5047 size_t len;
5048 ASSERT_TRUE(BIO_mem_contents(bio.get(), &data, &len));
5049 EXPECT_EQ(expected_rfc2253, std::string(data, data + len));
5050 };
5051
5052 check_name("");
5053
5054 // |loc| = -1, |set| = 0 appends as new RDNs.
5055 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5056 name.get(), NID_organizationName, MBSTRING_UTF8,
5057 reinterpret_cast<const unsigned char *>("Org"), /*len=*/-1, /*loc=*/-1,
5058 /*set=*/0));
5059 check_name("O=Org");
5060
5061 // |loc| = -1, |set| = 0 appends as new RDNs.
5062 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5063 name.get(), NID_commonName, MBSTRING_UTF8,
5064 reinterpret_cast<const unsigned char *>("Name"), /*len=*/-1, /*loc=*/-1,
5065 /*set=*/0));
5066 check_name("CN=Name,O=Org");
5067
5068 // Inserting in the middle of the set, but with |set| = 0 inserts a new RDN
5069 // and fixes the "set" values as needed.
5070 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5071 name.get(), NID_organizationalUnitName, MBSTRING_UTF8,
5072 reinterpret_cast<const unsigned char *>("Unit"), /*len=*/-1, /*loc=*/1,
5073 /*set=*/0));
5074 check_name("CN=Name,OU=Unit,O=Org");
5075
5076 // |set = -1| adds to the previous entry's RDN. (Although putting O and OU at
5077 // the same level makes little sense, the test is written this way to check
5078 // the function isn't using attribute types to order things.)
5079 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5080 name.get(), NID_organizationName, MBSTRING_UTF8,
5081 reinterpret_cast<const unsigned char *>("Org2"), /*len=*/-1, /*loc=*/2,
5082 /*set=*/-1));
5083 check_name("CN=Name,O=Org2+OU=Unit,O=Org");
5084
5085 // |set| = 1 adds to the next entry's RDN.
5086 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5087 name.get(), NID_commonName, MBSTRING_UTF8,
5088 reinterpret_cast<const unsigned char *>("Name2"), /*len=*/-1, /*loc=*/2,
5089 /*set=*/-1));
5090 check_name("CN=Name,O=Org2+CN=Name2+OU=Unit,O=Org");
5091
5092 // If there is no previous RDN, |set| = -1 makes a new RDN.
5093 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5094 name.get(), NID_countryName, MBSTRING_UTF8,
5095 reinterpret_cast<const unsigned char *>("US"), /*len=*/-1, /*loc=*/0,
5096 /*set=*/-1));
5097 check_name("CN=Name,O=Org2+CN=Name2+OU=Unit,O=Org,C=US");
5098
5099 // Likewise if there is no next RDN.
5100 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5101 name.get(), NID_commonName, MBSTRING_UTF8,
5102 reinterpret_cast<const unsigned char *>("Name3"), /*len=*/-1, /*loc=*/-1,
5103 /*set=*/1));
5104 check_name("CN=Name3,CN=Name,O=Org2+CN=Name2+OU=Unit,O=Org,C=US");
5105
5106 // If |set| = 0 and we insert in the middle of an existing RDN, it adds an
5107 // RDN boundary after the entry but not before. This is a quirk of how the
5108 // function is implemented and hopefully not something any caller depends on.
5109 ASSERT_TRUE(X509_NAME_add_entry_by_NID(
5110 name.get(), NID_commonName, MBSTRING_UTF8,
5111 reinterpret_cast<const unsigned char *>("Name4"), /*len=*/-1, /*loc=*/3,
5112 /*set=*/0));
5113 check_name("CN=Name3,CN=Name,O=Org2+CN=Name2,CN=Name4+OU=Unit,O=Org,C=US");
5114
5115 // Entries may be deleted.
5116 X509_NAME_ENTRY_free(X509_NAME_delete_entry(name.get(), 7));
5117 check_name("CN=Name,O=Org2+CN=Name2,CN=Name4+OU=Unit,O=Org,C=US");
5118
5119 // When deleting the only attribute in an RDN, index invariants should still
5120 // hold.
5121 X509_NAME_ENTRY_free(X509_NAME_delete_entry(name.get(), 0));
5122 check_name("CN=Name,O=Org2+CN=Name2,CN=Name4+OU=Unit,O=Org");
5123
5124 // Index invariants also hold when deleting attributes from non-singular RDNs.
5125 X509_NAME_ENTRY_free(X509_NAME_delete_entry(name.get(), 1));
5126 check_name("CN=Name,O=Org2+CN=Name2,CN=Name4,O=Org");
5127 X509_NAME_ENTRY_free(X509_NAME_delete_entry(name.get(), 1));
5128 check_name("CN=Name,O=Org2+CN=Name2,O=Org");
5129
5130 // Same as above, but delete the second attribute first.
5131 X509_NAME_ENTRY_free(X509_NAME_delete_entry(name.get(), 2));
5132 check_name("CN=Name,CN=Name2,O=Org");
5133 X509_NAME_ENTRY_free(X509_NAME_delete_entry(name.get(), 1));
5134 check_name("CN=Name,O=Org");
5135}
Emily Starkfd522962022-09-07 15:54:07 -07005136
5137// Tests that non-integer types are rejected when passed as an argument to
5138// X509_set_serialNumber().
5139TEST(X509Test, SetSerialNumberChecksASN1StringType) {
5140 bssl::UniquePtr<X509> root = CertFromPEM(kRootCAPEM);
5141 ASSERT_TRUE(root);
5142
5143 // Passing an IA5String to X509_set_serialNumber() should fail.
5144 bssl::UniquePtr<ASN1_IA5STRING> str(ASN1_IA5STRING_new());
5145 ASSERT_TRUE(str);
David Benjamina61e7472022-09-23 15:04:20 -04005146 EXPECT_FALSE(X509_set_serialNumber(root.get(), str.get()));
5147
5148 // Passing a negative serial number is allowed. While invalid, we do accept
5149 // them and some callers rely in this for tests.
5150 bssl::UniquePtr<ASN1_INTEGER> serial(ASN1_INTEGER_new());
5151 ASSERT_TRUE(serial);
David Benjamincab31f62022-09-23 15:22:39 -04005152 ASSERT_TRUE(ASN1_INTEGER_set_int64(serial.get(), -1));
David Benjamina61e7472022-09-23 15:04:20 -04005153 ASSERT_TRUE(X509_set_serialNumber(root.get(), serial.get()));
5154 int64_t val;
5155 ASSERT_TRUE(ASN1_INTEGER_get_int64(&val, X509_get0_serialNumber(root.get())));
5156 EXPECT_EQ(-1, val);
Emily Starkfd522962022-09-07 15:54:07 -07005157}
David Benjamind1b20a92022-12-13 17:10:09 -05005158
5159TEST(X509Test, Policy) {
5160 bssl::UniquePtr<ASN1_OBJECT> oid1(
5161 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.1", /*dont_search_names=*/1));
5162 ASSERT_TRUE(oid1);
5163 bssl::UniquePtr<ASN1_OBJECT> oid2(
5164 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.2", /*dont_search_names=*/1));
5165 ASSERT_TRUE(oid2);
5166 bssl::UniquePtr<ASN1_OBJECT> oid3(
5167 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.3", /*dont_search_names=*/1));
5168 ASSERT_TRUE(oid3);
David Benjamin31bad252022-12-14 14:58:26 -05005169 bssl::UniquePtr<ASN1_OBJECT> oid4(
5170 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.4", /*dont_search_names=*/1));
5171 ASSERT_TRUE(oid4);
5172 bssl::UniquePtr<ASN1_OBJECT> oid5(
5173 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.5", /*dont_search_names=*/1));
5174 ASSERT_TRUE(oid5);
David Benjamind1b20a92022-12-13 17:10:09 -05005175
5176 bssl::UniquePtr<X509> root(
5177 CertFromPEM(GetTestData("crypto/x509/test/policy_root.pem").c_str()));
5178 ASSERT_TRUE(root);
David Benjaminba68ca02023-01-20 14:50:17 -05005179 bssl::UniquePtr<X509> root_cross_inhibit_mapping(CertFromPEM(
5180 GetTestData("crypto/x509/test/policy_root_cross_inhibit_mapping.pem")
5181 .c_str()));
5182 ASSERT_TRUE(root_cross_inhibit_mapping);
5183 bssl::UniquePtr<X509> root2(
5184 CertFromPEM(GetTestData("crypto/x509/test/policy_root2.pem").c_str()));
5185 ASSERT_TRUE(root2);
David Benjamind1b20a92022-12-13 17:10:09 -05005186 bssl::UniquePtr<X509> intermediate(CertFromPEM(
5187 GetTestData("crypto/x509/test/policy_intermediate.pem").c_str()));
5188 ASSERT_TRUE(intermediate);
David Benjamin6d690062022-12-14 14:29:21 -05005189 bssl::UniquePtr<X509> intermediate_any(CertFromPEM(
5190 GetTestData("crypto/x509/test/policy_intermediate_any.pem").c_str()));
5191 ASSERT_TRUE(intermediate_any);
David Benjamin837ade72022-12-13 19:59:48 -05005192 bssl::UniquePtr<X509> intermediate_duplicate(CertFromPEM(
5193 GetTestData("crypto/x509/test/policy_intermediate_duplicate.pem")
5194 .c_str()));
5195 ASSERT_TRUE(intermediate_duplicate);
David Benjamin31bad252022-12-14 14:58:26 -05005196 bssl::UniquePtr<X509> intermediate_invalid(CertFromPEM(
5197 GetTestData("crypto/x509/test/policy_intermediate_invalid.pem").c_str()));
5198 ASSERT_TRUE(intermediate_invalid);
5199 bssl::UniquePtr<X509> intermediate_mapped(CertFromPEM(
5200 GetTestData("crypto/x509/test/policy_intermediate_mapped.pem")
5201 .c_str()));
5202 ASSERT_TRUE(intermediate_mapped);
5203 bssl::UniquePtr<X509> intermediate_mapped_any(CertFromPEM(
5204 GetTestData("crypto/x509/test/policy_intermediate_mapped_any.pem")
5205 .c_str()));
5206 ASSERT_TRUE(intermediate_mapped_any);
David Benjamin59b53a52023-01-04 17:29:24 -08005207 bssl::UniquePtr<X509> intermediate_mapped_oid3(CertFromPEM(
5208 GetTestData("crypto/x509/test/policy_intermediate_mapped_oid3.pem")
5209 .c_str()));
5210 ASSERT_TRUE(intermediate_mapped_oid3);
David Benjamin5f6d57a2022-12-13 23:20:24 -05005211 bssl::UniquePtr<X509> intermediate_require(CertFromPEM(
David Benjamin6d690062022-12-14 14:29:21 -05005212 GetTestData("crypto/x509/test/policy_intermediate_require.pem").c_str()));
David Benjamin5f6d57a2022-12-13 23:20:24 -05005213 ASSERT_TRUE(intermediate_require);
David Benjamin03081312023-01-11 20:55:44 -05005214 bssl::UniquePtr<X509> intermediate_require1(CertFromPEM(
5215 GetTestData("crypto/x509/test/policy_intermediate_require1.pem")
5216 .c_str()));
5217 ASSERT_TRUE(intermediate_require1);
5218 bssl::UniquePtr<X509> intermediate_require2(CertFromPEM(
5219 GetTestData("crypto/x509/test/policy_intermediate_require2.pem")
5220 .c_str()));
5221 ASSERT_TRUE(intermediate_require2);
David Benjamin5f6d57a2022-12-13 23:20:24 -05005222 bssl::UniquePtr<X509> intermediate_require_duplicate(CertFromPEM(
5223 GetTestData("crypto/x509/test/policy_intermediate_require_duplicate.pem")
5224 .c_str()));
5225 ASSERT_TRUE(intermediate_require_duplicate);
5226 bssl::UniquePtr<X509> intermediate_require_no_policies(CertFromPEM(
5227 GetTestData(
5228 "crypto/x509/test/policy_intermediate_require_no_policies.pem")
5229 .c_str()));
5230 ASSERT_TRUE(intermediate_require_no_policies);
David Benjamind1b20a92022-12-13 17:10:09 -05005231 bssl::UniquePtr<X509> leaf(
5232 CertFromPEM(GetTestData("crypto/x509/test/policy_leaf.pem").c_str()));
5233 ASSERT_TRUE(leaf);
David Benjamin6d690062022-12-14 14:29:21 -05005234 bssl::UniquePtr<X509> leaf_any(
5235 CertFromPEM(GetTestData("crypto/x509/test/policy_leaf_any.pem").c_str()));
5236 ASSERT_TRUE(leaf_any);
David Benjamin837ade72022-12-13 19:59:48 -05005237 bssl::UniquePtr<X509> leaf_duplicate(CertFromPEM(
5238 GetTestData("crypto/x509/test/policy_leaf_duplicate.pem").c_str()));
5239 ASSERT_TRUE(leaf_duplicate);
David Benjamin31bad252022-12-14 14:58:26 -05005240 bssl::UniquePtr<X509> leaf_invalid(CertFromPEM(
5241 GetTestData("crypto/x509/test/policy_leaf_invalid.pem").c_str()));
5242 ASSERT_TRUE(leaf_invalid);
5243 bssl::UniquePtr<X509> leaf_oid1(CertFromPEM(
5244 GetTestData("crypto/x509/test/policy_leaf_oid1.pem").c_str()));
5245 ASSERT_TRUE(leaf_oid1);
5246 bssl::UniquePtr<X509> leaf_oid2(CertFromPEM(
5247 GetTestData("crypto/x509/test/policy_leaf_oid2.pem").c_str()));
5248 ASSERT_TRUE(leaf_oid2);
5249 bssl::UniquePtr<X509> leaf_oid3(CertFromPEM(
5250 GetTestData("crypto/x509/test/policy_leaf_oid3.pem").c_str()));
5251 ASSERT_TRUE(leaf_oid3);
5252 bssl::UniquePtr<X509> leaf_oid4(CertFromPEM(
5253 GetTestData("crypto/x509/test/policy_leaf_oid4.pem").c_str()));
5254 ASSERT_TRUE(leaf_oid4);
5255 bssl::UniquePtr<X509> leaf_oid5(CertFromPEM(
5256 GetTestData("crypto/x509/test/policy_leaf_oid5.pem").c_str()));
5257 ASSERT_TRUE(leaf_oid5);
David Benjamin03081312023-01-11 20:55:44 -05005258 bssl::UniquePtr<X509> leaf_require(CertFromPEM(
5259 GetTestData("crypto/x509/test/policy_leaf_require.pem").c_str()));
5260 ASSERT_TRUE(leaf_require);
5261 bssl::UniquePtr<X509> leaf_require1(CertFromPEM(
5262 GetTestData("crypto/x509/test/policy_leaf_require1.pem").c_str()));
5263 ASSERT_TRUE(leaf_require1);
David Benjamind1b20a92022-12-13 17:10:09 -05005264
5265 // By default, OpenSSL does not check policies, so even syntax errors in the
5266 // certificatePolicies extension go unnoticed. (This is probably not
5267 // important.)
5268 EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()},
5269 {intermediate.get()}, /*crls=*/{}));
5270 EXPECT_EQ(X509_V_OK, Verify(leaf_invalid.get(), {root.get()},
5271 {intermediate.get()}, /*crls=*/{}));
5272
5273 auto set_policies = [](X509_VERIFY_PARAM *param,
5274 std::vector<const ASN1_OBJECT *> oids) {
5275 for (const ASN1_OBJECT *oid : oids) {
5276 bssl::UniquePtr<ASN1_OBJECT> copy(OBJ_dup(oid));
5277 ASSERT_TRUE(copy);
5278 ASSERT_TRUE(X509_VERIFY_PARAM_add0_policy(param, copy.get()));
5279 copy.release(); // |X509_VERIFY_PARAM_add0_policy| takes ownership on
5280 // success.
David Benjamin5f6d57a2022-12-13 23:20:24 -05005281 // TODO(davidben): |X509_VERIFY_PARAM_add0_policy| does not set this flag,
5282 // while |X509_VERIFY_PARAM_set1_policies| does. Is this a bug?
5283 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_POLICY_CHECK);
David Benjamind1b20a92022-12-13 17:10:09 -05005284 }
5285 };
5286
5287 // The chain is good for |oid1| and |oid2|, but not |oid3|.
5288 EXPECT_EQ(X509_V_OK,
5289 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5290 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5291 set_policies(param, {oid1.get()});
5292 }));
5293 EXPECT_EQ(X509_V_OK,
5294 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5295 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5296 set_policies(param, {oid2.get()});
5297 }));
5298 EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY,
5299 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5300 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5301 set_policies(param, {oid3.get()});
5302 }));
5303 EXPECT_EQ(X509_V_OK,
5304 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5305 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5306 set_policies(param, {oid1.get(), oid2.get()});
5307 }));
5308 EXPECT_EQ(X509_V_OK,
5309 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5310 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5311 set_policies(param, {oid1.get(), oid3.get()});
5312 }));
5313
David Benjamin837ade72022-12-13 19:59:48 -05005314 // The policy extension cannot be parsed.
David Benjamind1b20a92022-12-13 17:10:09 -05005315 EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
5316 Verify(leaf.get(), {root.get()}, {intermediate_invalid.get()},
5317 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5318 [&](X509_VERIFY_PARAM *param) {
5319 set_policies(param, {oid1.get()});
5320 }));
David Benjamin837ade72022-12-13 19:59:48 -05005321 EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
5322 Verify(leaf_invalid.get(), {root.get()}, {intermediate.get()},
5323 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5324 [&](X509_VERIFY_PARAM *param) {
5325 set_policies(param, {oid1.get()});
5326 }));
5327
5328 // There is a duplicate policy in the policy extension.
5329 EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
5330 Verify(leaf.get(), {root.get()}, {intermediate_duplicate.get()},
5331 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5332 [&](X509_VERIFY_PARAM *param) {
5333 set_policies(param, {oid1.get()});
5334 }));
David Benjamind1b20a92022-12-13 17:10:09 -05005335
5336 // The policy extension in the leaf cannot be parsed.
5337 EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
David Benjamin837ade72022-12-13 19:59:48 -05005338 Verify(leaf_duplicate.get(), {root.get()}, {intermediate.get()},
David Benjamind1b20a92022-12-13 17:10:09 -05005339 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5340 [&](X509_VERIFY_PARAM *param) {
5341 set_policies(param, {oid1.get()});
5342 }));
David Benjamin5f6d57a2022-12-13 23:20:24 -05005343
5344 // Without |X509_V_FLAG_EXPLICIT_POLICY|, the policy tree is built and
5345 // intersected with user-specified policies, but it is not required to result
5346 // in any valid policies.
5347 EXPECT_EQ(X509_V_OK,
5348 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5349 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5350 set_policies(param, {oid1.get()});
5351 }));
5352 EXPECT_EQ(X509_V_OK,
5353 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5354 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5355 set_policies(param, {oid3.get()});
5356 }));
5357
5358 // However, a CA with policy constraints can require an explicit policy.
5359 EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()},
5360 {intermediate_require.get()}, /*crls=*/{},
5361 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5362 set_policies(param, {oid1.get()});
5363 }));
5364 EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY,
5365 Verify(leaf.get(), {root.get()}, {intermediate_require.get()},
5366 /*crls=*/{},
5367 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5368 set_policies(param, {oid3.get()});
5369 }));
5370
David Benjamin03081312023-01-11 20:55:44 -05005371 // A leaf can also set requireExplicitPolicy.
5372 EXPECT_EQ(X509_V_OK, Verify(leaf_require.get(), {root.get()},
5373 {intermediate.get()}, /*crls=*/{},
5374 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5375 set_policies(param, {oid1.get()});
5376 }));
5377 EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY,
5378 Verify(leaf_require.get(), {root.get()}, {intermediate.get()},
5379 /*crls=*/{},
5380 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5381 set_policies(param, {oid3.get()});
5382 }));
5383
5384 // requireExplicitPolicy is a count of certificates to skip. If the value is
5385 // not zero by the end of the chain, it doesn't count.
5386 EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY,
5387 Verify(leaf.get(), {root.get()}, {intermediate_require1.get()},
5388 /*crls=*/{},
5389 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5390 set_policies(param, {oid3.get()});
5391 }));
5392 EXPECT_EQ(X509_V_OK,
5393 Verify(leaf.get(), {root.get()}, {intermediate_require2.get()},
5394 /*crls=*/{},
5395 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5396 set_policies(param, {oid3.get()});
5397 }));
5398 EXPECT_EQ(X509_V_OK,
5399 Verify(leaf_require1.get(), {root.get()}, {intermediate.get()},
5400 /*crls=*/{},
5401 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5402 set_policies(param, {oid3.get()});
5403 }));
5404
5405 // If multiple certificates specify the constraint, the more constrained value
5406 // wins.
5407 EXPECT_EQ(
5408 X509_V_ERR_NO_EXPLICIT_POLICY,
5409 Verify(leaf_require1.get(), {root.get()}, {intermediate_require1.get()},
5410 /*crls=*/{},
5411 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5412 set_policies(param, {oid3.get()});
5413 }));
5414 EXPECT_EQ(
5415 X509_V_ERR_NO_EXPLICIT_POLICY,
5416 Verify(leaf_require.get(), {root.get()}, {intermediate_require2.get()},
5417 /*crls=*/{},
5418 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5419 set_policies(param, {oid3.get()});
5420 }));
5421
David Benjamin5f6d57a2022-12-13 23:20:24 -05005422 // An intermediate that requires an explicit policy, but then specifies no
5423 // policies should fail verification as a result.
5424 EXPECT_EQ(X509_V_ERR_NO_EXPLICIT_POLICY,
5425 Verify(leaf.get(), {root.get()},
5426 {intermediate_require_no_policies.get()}, /*crls=*/{},
5427 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5428 set_policies(param, {oid1.get()});
5429 }));
5430
5431 // A constrained intermediate's policy extension has a duplicate policy, which
5432 // is invalid. Historically this, and the above case, leaked memory.
5433 EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
5434 Verify(leaf.get(), {root.get()},
5435 {intermediate_require_duplicate.get()}, /*crls=*/{},
5436 /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
5437 set_policies(param, {oid1.get()});
5438 }));
David Benjamin6d690062022-12-14 14:29:21 -05005439
5440 // The leaf asserts anyPolicy, but the intermediate does not. The resulting
5441 // valid policies are the intersection.
David Benjamin03081312023-01-11 20:55:44 -05005442 EXPECT_EQ(
5443 X509_V_OK,
5444 Verify(leaf_any.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5445 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5446 set_policies(param, {oid1.get()});
5447 }));
5448 EXPECT_EQ(
5449 X509_V_ERR_NO_EXPLICIT_POLICY,
5450 Verify(leaf_any.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5451 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5452 set_policies(param, {oid3.get()});
5453 }));
David Benjamin6d690062022-12-14 14:29:21 -05005454
5455 // The intermediate asserts anyPolicy, but the leaf does not. The resulting
5456 // valid policies are the intersection.
5457 EXPECT_EQ(
5458 X509_V_OK,
5459 Verify(leaf.get(), {root.get()}, {intermediate_any.get()}, /*crls=*/{},
5460 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5461 set_policies(param, {oid1.get()});
5462 }));
5463 EXPECT_EQ(
5464 X509_V_ERR_NO_EXPLICIT_POLICY,
5465 Verify(leaf.get(), {root.get()}, {intermediate_any.get()}, /*crls=*/{},
5466 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5467 set_policies(param, {oid3.get()});
5468 }));
5469
5470 // Both assert anyPolicy. All policies are valid.
5471 EXPECT_EQ(X509_V_OK,
5472 Verify(leaf_any.get(), {root.get()}, {intermediate_any.get()},
5473 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5474 [&](X509_VERIFY_PARAM *param) {
5475 set_policies(param, {oid1.get()});
5476 }));
5477 EXPECT_EQ(X509_V_OK,
5478 Verify(leaf_any.get(), {root.get()}, {intermediate_any.get()},
5479 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5480 [&](X509_VERIFY_PARAM *param) {
5481 set_policies(param, {oid3.get()});
5482 }));
David Benjamin31bad252022-12-14 14:58:26 -05005483
David Benjamin1f2529d2023-01-04 15:34:46 -08005484 // With just a trust anchor, policy checking silently succeeds.
5485 EXPECT_EQ(X509_V_OK, Verify(root.get(), {root.get()}, {},
5486 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5487 [&](X509_VERIFY_PARAM *param) {
5488 set_policies(param, {oid1.get()});
5489 }));
5490
David Benjamin31bad252022-12-14 14:58:26 -05005491 for (bool use_any : {false, true}) {
5492 SCOPED_TRACE(use_any);
5493 X509 *cert =
5494 use_any ? intermediate_mapped_any.get() : intermediate_mapped.get();
5495 // OID3 is mapped to {OID1, OID2}, which means OID1 and OID2 (or both) are
5496 // acceptable for OID3.
5497 EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {cert},
5498 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5499 [&](X509_VERIFY_PARAM *param) {
5500 set_policies(param, {oid3.get()});
5501 }));
5502 EXPECT_EQ(X509_V_OK, Verify(leaf_oid1.get(), {root.get()}, {cert},
5503 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5504 [&](X509_VERIFY_PARAM *param) {
5505 set_policies(param, {oid3.get()});
5506 }));
5507 EXPECT_EQ(X509_V_OK, Verify(leaf_oid2.get(), {root.get()}, {cert},
5508 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5509 [&](X509_VERIFY_PARAM *param) {
5510 set_policies(param, {oid3.get()});
5511 }));
5512
5513 // If the intermediate's policies were anyPolicy, OID3 at the leaf, despite
5514 // being mapped, is still acceptable as OID3 at the root. Despite the OID3
5515 // having expected_policy_set = {OID1, OID2}, it can match the anyPolicy
5516 // node instead.
5517 //
5518 // If the intermediate's policies listed OIDs explicitly, OID3 at the leaf
5519 // is not acceptable as OID3 at the root. OID3 has expected_polciy_set =
5520 // {OID1, OID2} and no other node allows OID3.
5521 EXPECT_EQ(use_any ? X509_V_OK : X509_V_ERR_NO_EXPLICIT_POLICY,
5522 Verify(leaf_oid3.get(), {root.get()}, {cert},
5523 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5524 [&](X509_VERIFY_PARAM *param) {
5525 set_policies(param, {oid3.get()});
5526 }));
5527
5528 // If the intermediate's policies were anyPolicy, OID1 at the leaf is no
5529 // longer acceptable as OID1 at the root because policies only match
5530 // anyPolicy when they match no other policy.
5531 //
5532 // If the intermediate's policies listed OIDs explicitly, OID1 at the leaf
5533 // is acceptable as OID1 at the root because it will match both OID1 and
5534 // OID3 (mapped) policies.
5535 EXPECT_EQ(use_any ? X509_V_ERR_NO_EXPLICIT_POLICY : X509_V_OK,
5536 Verify(leaf_oid1.get(), {root.get()}, {cert},
5537 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5538 [&](X509_VERIFY_PARAM *param) {
5539 set_policies(param, {oid1.get()});
5540 }));
5541
5542 // All pairs of OID4 and OID5 are mapped together, so either can stand for
5543 // the other.
5544 EXPECT_EQ(X509_V_OK, Verify(leaf_oid4.get(), {root.get()}, {cert},
5545 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5546 [&](X509_VERIFY_PARAM *param) {
5547 set_policies(param, {oid4.get()});
5548 }));
5549 EXPECT_EQ(X509_V_OK, Verify(leaf_oid4.get(), {root.get()}, {cert},
5550 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5551 [&](X509_VERIFY_PARAM *param) {
5552 set_policies(param, {oid5.get()});
5553 }));
5554 EXPECT_EQ(X509_V_OK, Verify(leaf_oid5.get(), {root.get()}, {cert},
5555 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5556 [&](X509_VERIFY_PARAM *param) {
5557 set_policies(param, {oid4.get()});
5558 }));
5559 EXPECT_EQ(X509_V_OK, Verify(leaf_oid5.get(), {root.get()}, {cert},
5560 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5561 [&](X509_VERIFY_PARAM *param) {
5562 set_policies(param, {oid5.get()});
5563 }));
5564
5565 EXPECT_EQ(X509_V_OK, Verify(leaf_oid4.get(), {root.get()}, {cert},
5566 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5567 [&](X509_VERIFY_PARAM *param) {
5568 set_policies(param, {oid4.get(), oid5.get()});
5569 }));
5570 }
David Benjamin59b53a52023-01-04 17:29:24 -08005571
5572 // Although |intermediate_mapped_oid3| contains many mappings, it only accepts
5573 // OID3. Nodes should not be created for the other mappings.
5574 EXPECT_EQ(X509_V_OK, Verify(leaf_oid1.get(), {root.get()},
5575 {intermediate_mapped_oid3.get()},
5576 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5577 [&](X509_VERIFY_PARAM *param) {
5578 set_policies(param, {oid3.get()});
5579 }));
5580 EXPECT_EQ(
5581 X509_V_ERR_NO_EXPLICIT_POLICY,
5582 Verify(leaf_oid4.get(), {root.get()}, {intermediate_mapped_oid3.get()},
5583 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5584 [&](X509_VERIFY_PARAM *param) {
5585 set_policies(param, {oid4.get()});
5586 }));
David Benjaminba68ca02023-01-20 14:50:17 -05005587
5588 // Policy mapping can be inhibited, either by the caller or a certificate in
5589 // the chain, in which case mapped policies are unassertable (apart from some
5590 // anyPolicy edge cases).
5591 EXPECT_EQ(
5592 X509_V_ERR_NO_EXPLICIT_POLICY,
5593 Verify(leaf_oid1.get(), {root.get()}, {intermediate_mapped_oid3.get()},
5594 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY | X509_V_FLAG_INHIBIT_MAP,
5595 [&](X509_VERIFY_PARAM *param) {
5596 set_policies(param, {oid3.get()});
5597 }));
5598 EXPECT_EQ(
5599 X509_V_ERR_NO_EXPLICIT_POLICY,
5600 Verify(leaf_oid1.get(), {root2.get()},
5601 {intermediate_mapped_oid3.get(), root_cross_inhibit_mapping.get()},
5602 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5603 [&](X509_VERIFY_PARAM *param) {
5604 set_policies(param, {oid3.get()});
5605 }));
David Benjamind1b20a92022-12-13 17:10:09 -05005606}
David Benjamin7c81c5f2022-12-29 14:13:24 -05005607
David Benjamin029d0e72022-12-26 19:38:40 -05005608#if defined(OPENSSL_THREADS)
5609// A similar test to the above, but ensures the various bits of intermediate
5610// state are computed safely.
5611TEST(X509Test, PolicyThreads) {
5612 const size_t kNumThreads = 10;
5613
5614 bssl::UniquePtr<ASN1_OBJECT> oid1(
5615 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.1", /*dont_search_names=*/1));
5616 ASSERT_TRUE(oid1);
5617 bssl::UniquePtr<ASN1_OBJECT> oid2(
5618 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.2", /*dont_search_names=*/1));
5619 ASSERT_TRUE(oid2);
5620 bssl::UniquePtr<ASN1_OBJECT> oid3(
5621 OBJ_txt2obj("1.2.840.113554.4.1.72585.2.3", /*dont_search_names=*/1));
5622 ASSERT_TRUE(oid3);
5623
5624 auto set_policies = [](X509_VERIFY_PARAM *param,
5625 std::vector<const ASN1_OBJECT *> oids) {
5626 for (const ASN1_OBJECT *oid : oids) {
5627 bssl::UniquePtr<ASN1_OBJECT> copy(OBJ_dup(oid));
5628 ASSERT_TRUE(copy);
5629 ASSERT_TRUE(X509_VERIFY_PARAM_add0_policy(param, copy.get()));
5630 copy.release(); // |X509_VERIFY_PARAM_add0_policy| takes ownership on
5631 // success.
5632 }
5633 };
5634
5635 {
5636 bssl::UniquePtr<X509> root(
5637 CertFromPEM(GetTestData("crypto/x509/test/policy_root.pem").c_str()));
5638 ASSERT_TRUE(root);
5639 bssl::UniquePtr<X509> intermediate(CertFromPEM(
5640 GetTestData("crypto/x509/test/policy_intermediate.pem").c_str()));
5641 ASSERT_TRUE(intermediate);
5642 bssl::UniquePtr<X509> leaf(
5643 CertFromPEM(GetTestData("crypto/x509/test/policy_leaf.pem").c_str()));
5644 ASSERT_TRUE(leaf);
5645
5646 std::vector<std::thread> threads;
5647 for (size_t i = 0; i < kNumThreads; i++) {
5648 threads.emplace_back([&] {
5649 EXPECT_EQ(
5650 X509_V_OK,
5651 Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{},
5652 X509_V_FLAG_EXPLICIT_POLICY, [&](X509_VERIFY_PARAM *param) {
5653 set_policies(param, {oid1.get()});
5654 }));
5655 });
5656 }
5657 for (auto &thread : threads) {
5658 thread.join();
5659 }
5660 }
5661
5662 {
5663 bssl::UniquePtr<X509> root(
5664 CertFromPEM(GetTestData("crypto/x509/test/policy_root.pem").c_str()));
5665 ASSERT_TRUE(root);
5666 bssl::UniquePtr<X509> intermediate(CertFromPEM(
5667 GetTestData("crypto/x509/test/policy_intermediate.pem").c_str()));
5668 ASSERT_TRUE(intermediate);
5669 bssl::UniquePtr<X509> leaf_invalid(CertFromPEM(
5670 GetTestData("crypto/x509/test/policy_leaf_invalid.pem").c_str()));
5671 ASSERT_TRUE(leaf_invalid);
5672
5673
5674 std::vector<std::thread> threads;
5675 for (size_t i = 0; i < kNumThreads; i++) {
5676 threads.emplace_back([&] {
5677 EXPECT_EQ(X509_V_ERR_INVALID_POLICY_EXTENSION,
5678 Verify(leaf_invalid.get(), {root.get()}, {intermediate.get()},
5679 /*crls=*/{}, X509_V_FLAG_EXPLICIT_POLICY,
5680 [&](X509_VERIFY_PARAM *param) {
5681 set_policies(param, {oid1.get()});
5682 }));
5683 });
5684 }
5685 for (auto &thread : threads) {
5686 thread.join();
5687 }
5688 }
5689}
5690#endif // OPENSSL_THREADS
5691
David Benjamin7c81c5f2022-12-29 14:13:24 -05005692TEST(X509Test, ExtensionFromConf) {
5693 static const char kTestOID[] = "1.2.840.113554.4.1.72585.2";
5694 const struct {
5695 const char *name;
5696 const char *value;
5697 const char *conf;
5698 // expected is the resulting extension, encoded in DER, or the empty string
5699 // if an error is expected.
5700 std::vector<uint8_t> expected;
5701 } kTests[] = {
5702 // Many extensions have built-in syntax.
5703 {"basicConstraints",
5704 "critical,CA:true",
5705 nullptr,
5706 {0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
5707 0x30, 0x03, 0x01, 0x01, 0xff}},
5708
5709 // Extension contents may be referenced from a config section.
5710 {"basicConstraints",
5711 "critical,@section",
5712 "[section]\nCA = true\n",
5713 {0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
5714 0x30, 0x03, 0x01, 0x01, 0xff}},
5715
David Benjamin871704b2022-12-29 22:02:28 -05005716 // If no config is provided, this should fail.
5717 {"basicConstraints", "critical,@section", nullptr, {}},
David Benjamin7c81c5f2022-12-29 14:13:24 -05005718
5719 // The "DER:" prefix just specifies an arbitrary byte string. Colons
5720 // separators are ignored.
5721 {kTestOID, "DER:0001020304", nullptr, {0x30, 0x15, 0x06, 0x0c, 0x2a, 0x86,
5722 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5723 0x84, 0xb7, 0x09, 0x02, 0x04, 0x05,
5724 0x00, 0x01, 0x02, 0x03, 0x04}},
5725 {kTestOID,
5726 "DER:00:01:02:03:04",
5727 nullptr,
5728 {0x30, 0x15, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5729 0x84, 0xb7, 0x09, 0x02, 0x04, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04}},
5730 {kTestOID, "DER:invalid hex", nullptr, {}},
5731
5732 // The "ASN1:" prefix implements a complex language for describing ASN.1
5733 // structures. See
5734 // https://www.openssl.org/docs/man1.1.1/man3/ASN1_generate_nconf.html
5735 {kTestOID, "ASN1:invalid", nullptr, {}},
5736 {kTestOID,
5737 "ASN1:BOOLEAN:TRUE",
5738 nullptr,
5739 {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5740 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03, 0x01, 0x01, 0xff}},
5741 {kTestOID, "ASN1:BOOL:yes", nullptr, {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86,
5742 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5743 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03,
5744 0x01, 0x01, 0xff}},
5745 {kTestOID,
5746 "ASN1:BOOLEAN:NO",
5747 nullptr,
5748 {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5749 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03, 0x01, 0x01, 0x00}},
5750 {kTestOID,
5751 "ASN1:BOOLEAN", // Missing value
5752 nullptr,
5753 {}},
5754 {kTestOID, "ASN1:BOOLEAN:invalid", nullptr, {}},
5755 {kTestOID, "ASN1:BOOLEAN:TRUE,invalid", nullptr, {}},
5756
5757 {kTestOID, "ASN1:NULL", nullptr, {0x30, 0x12, 0x06, 0x0c, 0x2a,
5758 0x86, 0x48, 0x86, 0xf7, 0x12,
5759 0x04, 0x01, 0x84, 0xb7, 0x09,
5760 0x02, 0x04, 0x02, 0x05, 0x00}},
5761 {kTestOID, "ASN1:NULL,invalid", nullptr, {}},
5762 {kTestOID, "ASN1:NULL:invalid", nullptr, {}},
5763
5764 // Missing value.
5765 {kTestOID, "ASN1:INTEGER", nullptr, {}},
5766 {kTestOID, "ASN1:INTEGER:", nullptr, {}},
5767 {kTestOID, "ASN1:INTEGER,invalid", nullptr, {}},
5768
5769 // INTEGER may be decimal or hexadecimal.
5770 {kTestOID, "ASN1:INT:-0x10", nullptr, {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86,
5771 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5772 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03,
5773 0x02, 0x01, 0xf0}},
5774 {kTestOID, "ASN1:INT:-10", nullptr, {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86,
5775 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5776 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03,
5777 0x02, 0x01, 0xf6}},
5778 {kTestOID, "ASN1:INT:0", nullptr, {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86,
5779 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5780 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03,
5781 0x02, 0x01, 0x00}},
5782 {kTestOID,
5783 "ASN1:INTEGER:10",
5784 nullptr,
5785 {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5786 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03, 0x02, 0x01, 0x0a}},
5787 {kTestOID,
5788 "ASN1:INTEGER:0x10",
5789 nullptr,
5790 {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5791 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03, 0x02, 0x01, 0x10}},
5792
5793 {kTestOID, "ASN1:ENUM:0", nullptr, {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86,
5794 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5795 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03,
5796 0x0a, 0x01, 0x00}},
5797 {kTestOID,
5798 "ASN1:ENUMERATED:0",
5799 nullptr,
5800 {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5801 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03, 0x0a, 0x01, 0x00}},
5802
5803 // OIDs may be spelled out or specified by name.
5804 {kTestOID, "ASN1:OBJECT:invalid", nullptr, {}},
5805 {kTestOID,
5806 "ASN1:OBJECT:basicConstraints",
5807 nullptr,
5808 {0x30, 0x15, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5809 0x84, 0xb7, 0x09, 0x02, 0x04, 0x05, 0x06, 0x03, 0x55, 0x1d, 0x13}},
5810 {kTestOID,
5811 "ASN1:OBJECT:2.5.29.19",
5812 nullptr,
5813 {0x30, 0x15, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5814 0x84, 0xb7, 0x09, 0x02, 0x04, 0x05, 0x06, 0x03, 0x55, 0x1d, 0x13}},
5815 {kTestOID,
5816 "ASN1:OID:2.5.29.19",
5817 nullptr,
5818 {0x30, 0x15, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5819 0x84, 0xb7, 0x09, 0x02, 0x04, 0x05, 0x06, 0x03, 0x55, 0x1d, 0x13}},
5820
5821 {kTestOID, "ASN1:UTC:invalid", nullptr, {}},
5822 {kTestOID, "ASN1:UTC:20001231235959Z", nullptr, {}},
5823 {kTestOID, "ASN1:UTCTIME:invalid", nullptr, {}},
5824 {kTestOID,
5825 "ASN1:UTC:001231235959Z",
5826 nullptr,
5827 {0x30, 0x1f, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5828 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x0f, 0x17, 0x0d, 0x30, 0x30,
5829 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a}},
5830 {kTestOID,
5831 "ASN1:UTCTIME:001231235959Z",
5832 nullptr,
5833 {0x30, 0x1f, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5834 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x0f, 0x17, 0x0d, 0x30, 0x30,
5835 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a}},
5836
5837 {kTestOID, "ASN1:GENTIME:invalid", nullptr, {}},
5838 {kTestOID, "ASN1:GENTIME:001231235959Z", nullptr, {}},
5839 {kTestOID, "ASN1:GENERALIZEDTIME:invalid", nullptr, {}},
5840 {kTestOID,
5841 "ASN1:GENTIME:20001231235959Z",
5842 nullptr,
5843 {0x30, 0x21, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5844 0x84, 0xb7, 0x09, 0x02, 0x04, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x30, 0x30,
5845 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a}},
5846 {kTestOID,
5847 "ASN1:GENERALIZEDTIME:20001231235959Z",
5848 nullptr,
5849 {0x30, 0x21, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5850 0x84, 0xb7, 0x09, 0x02, 0x04, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x30, 0x30,
5851 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a}},
5852
5853 // The default input format for string types is ASCII, which is then
5854 // converted into the target string type.
5855 {kTestOID, "ASN1:UTF8:hello", nullptr, {0x30, 0x17, 0x06, 0x0c, 0x2a,
5856 0x86, 0x48, 0x86, 0xf7, 0x12,
5857 0x04, 0x01, 0x84, 0xb7, 0x09,
5858 0x02, 0x04, 0x07, 0x0c, 0x05,
5859 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5860 {kTestOID,
5861 "ASN1:UTF8String:hello",
5862 nullptr,
5863 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5864 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5865 0x0c, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5866 {kTestOID,
5867 "ASN1:UNIV:hello",
5868 nullptr,
5869 {0x30, 0x26, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
5870 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x16, 0x1c, 0x14,
5871 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00,
5872 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6f}},
5873 {kTestOID,
5874 "ASN1:UNIVERSALSTRING:hello",
5875 nullptr,
5876 {0x30, 0x26, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
5877 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x16, 0x1c, 0x14,
5878 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00,
5879 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6f}},
5880 {kTestOID,
5881 "ASN1:BMP:hello",
5882 nullptr,
5883 {0x30, 0x1c, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
5884 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x0c, 0x1e, 0x0a,
5885 0x00, 0x68, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f}},
5886 {kTestOID,
5887 "ASN1:BMPSTRING:hello",
5888 nullptr,
5889 {0x30, 0x1c, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
5890 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x0c, 0x1e, 0x0a,
5891 0x00, 0x68, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f}},
5892 {kTestOID, "ASN1:IA5:hello", nullptr, {0x30, 0x17, 0x06, 0x0c, 0x2a,
5893 0x86, 0x48, 0x86, 0xf7, 0x12,
5894 0x04, 0x01, 0x84, 0xb7, 0x09,
5895 0x02, 0x04, 0x07, 0x16, 0x05,
5896 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5897 {kTestOID,
5898 "ASN1:IA5STRING:hello",
5899 nullptr,
5900 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5901 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5902 0x16, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5903 {kTestOID,
5904 "ASN1:PRINTABLE:hello",
5905 nullptr,
5906 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5907 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5908 0x13, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5909 {kTestOID,
5910 "ASN1:PRINTABLESTRING:hello",
5911 nullptr,
5912 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5913 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5914 0x13, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5915 {kTestOID, "ASN1:T61:hello", nullptr, {0x30, 0x17, 0x06, 0x0c, 0x2a,
5916 0x86, 0x48, 0x86, 0xf7, 0x12,
5917 0x04, 0x01, 0x84, 0xb7, 0x09,
5918 0x02, 0x04, 0x07, 0x14, 0x05,
5919 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5920 {kTestOID,
5921 "ASN1:T61STRING:hello",
5922 nullptr,
5923 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5924 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5925 0x14, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5926 {kTestOID,
5927 "ASN1:TELETEXSTRING:hello",
5928 nullptr,
5929 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5930 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5931 0x14, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5932
5933 // FORMAT:UTF8 switches the input format to UTF-8. This should be
5934 // converted to the destination string, or rejected if invalid.
5935 {kTestOID,
5936 "ASN1:FORMAT:UTF8,UTF8:\xe2\x98\x83",
5937 nullptr,
5938 {0x30, 0x15, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
5939 0x84, 0xb7, 0x09, 0x02, 0x04, 0x05, 0x0c, 0x03, 0xe2, 0x98, 0x83}},
5940 {kTestOID,
5941 "ASN1:FORMAT:UTF8,UNIV:\xe2\x98\x83",
5942 nullptr,
5943 {0x30, 0x16, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86,
5944 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02,
5945 0x04, 0x06, 0x1c, 0x04, 0x00, 0x00, 0x26, 0x03}},
5946 {kTestOID,
5947 "ASN1:FORMAT:UTF8,BMP:\xe2\x98\x83",
5948 nullptr,
5949 {0x30, 0x14, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5950 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x04, 0x1e, 0x02, 0x26, 0x03}},
5951 {kTestOID, "ASN1:FORMAT:UTF8,IA5:\xe2\x98\x83", nullptr, {}},
5952 {kTestOID,
5953 "ASN1:FORMAT:UTF8,IA5:hello",
5954 nullptr,
5955 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5956 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5957 0x16, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5958 {kTestOID, "ASN1:FORMAT:UTF8,PRINTABLE:\xe2\x98\x83", nullptr, {}},
5959 {kTestOID,
5960 "ASN1:FORMAT:UTF8,PRINTABLE:hello",
5961 nullptr,
5962 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5963 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5964 0x13, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5965 {kTestOID, "ASN1:FORMAT:UTF8,T61:\xe2\x98\x83", nullptr, {}},
5966 {kTestOID,
5967 "ASN1:FORMAT:UTF8,T61:\xc3\xb7",
5968 nullptr,
5969 {0x30, 0x13, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
5970 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x03, 0x14, 0x01, 0xf7}},
5971
5972 // Invalid UTF-8.
5973 {kTestOID, "ASN1:FORMAT:UTF8,UTF8:\xff", nullptr, {}},
5974
5975 // We don't support these string types.
David Benjamin7c81c5f2022-12-29 14:13:24 -05005976 {kTestOID, "ASN1:NUMERIC:0", nullptr, {}},
5977 {kTestOID, "ASN1:NUMERICSTRING:0", nullptr, {}},
5978 {kTestOID, "ASN1:VISIBLE:hello", nullptr, {}},
5979 {kTestOID, "ASN1:VISIBLESTRING:hello", nullptr, {}},
5980 {kTestOID, "ASN1:GeneralString:hello", nullptr, {}},
5981
5982 // OCTET STRING and BIT STRING also default to ASCII, but also accept HEX.
5983 // BIT STRING interprets OCTET STRING formats by having zero unused bits.
5984 {kTestOID, "ASN1:OCT:hello", nullptr, {0x30, 0x17, 0x06, 0x0c, 0x2a,
5985 0x86, 0x48, 0x86, 0xf7, 0x12,
5986 0x04, 0x01, 0x84, 0xb7, 0x09,
5987 0x02, 0x04, 0x07, 0x04, 0x05,
5988 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5989 {kTestOID,
5990 "ASN1:OCTETSTRING:hello",
5991 nullptr,
5992 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5993 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
5994 0x04, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
5995 {kTestOID,
5996 "ASN1:FORMAT:HEX,OCT:0123abcd",
5997 nullptr,
5998 {0x30, 0x16, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86,
5999 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02,
6000 0x04, 0x06, 0x04, 0x04, 0x01, 0x23, 0xab, 0xcd}},
6001 {kTestOID,
6002 "ASN1:BITSTR:hello",
6003 nullptr,
6004 {0x30, 0x18, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
6005 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x08,
6006 0x03, 0x06, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
6007 {kTestOID,
6008 "ASN1:BITSTRING:hello",
6009 nullptr,
6010 {0x30, 0x18, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
6011 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x08,
6012 0x03, 0x06, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f}},
6013 {kTestOID,
6014 "ASN1:FORMAT:HEX,BITSTR:0123abcd",
6015 nullptr,
6016 {0x30, 0x17, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
6017 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x07,
6018 0x03, 0x05, 0x00, 0x01, 0x23, 0xab, 0xcd}},
6019
6020 {kTestOID, "ASN1:FORMAT:HEX,OCT:invalid hex", nullptr, {}},
6021
6022 // BIT STRING additionally supports a BITLIST type, which specifies a
6023 // list of bits to set.
6024 {kTestOID,
6025 "ASN1:FORMAT:BITLIST,BITSTR:1,5",
6026 nullptr,
6027 {0x30, 0x14, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
6028 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x04, 0x03, 0x02, 0x02, 0x44}},
6029
6030 {kTestOID, "ASN1:FORMAT:BITLIST,BITSTR:1,invalid,5", nullptr, {}},
6031 // TODO(davidben): Handle overflow and enable this test.
6032 // {kTestOID, "ASN1:FORMAT:BITLIST,BITSTR:4294967296", nullptr, {}},
6033
6034 // Unsupported formats for string types.
6035 {kTestOID, "ASN1:FORMAT:BITLIST,IA5:abcd", nullptr, {}},
6036 {kTestOID, "ASN1:FORMAT:BITLIST,UTF8:abcd", nullptr, {}},
6037 {kTestOID, "ASN1:FORMAT:BITLIST,OCT:abcd", nullptr, {}},
6038 {kTestOID, "ASN1:FORMAT:BITLIST,UTC:abcd", nullptr, {}},
6039 {kTestOID, "ASN1:FORMAT:HEX,IA5:abcd", nullptr, {}},
6040 {kTestOID, "ASN1:FORMAT:HEX,UTF8:abcd", nullptr, {}},
6041 {kTestOID, "ASN1:FORMAT:HEX,UTC:abcd", nullptr, {}},
6042 {kTestOID, "ASN1:FORMAT:UTF8,OCT:abcd", nullptr, {}},
6043 {kTestOID, "ASN1:FORMAT:UTF8,UTC:abcd", nullptr, {}},
6044
6045 // Invalid format type.
6046 {kTestOID, "ASN1:FORMAT:invalid,IA5:abcd", nullptr, {}},
6047
6048 // SEQUENCE and SET encode empty values when there is no value.
6049 {kTestOID, "ASN1:SEQ", nullptr, {0x30, 0x12, 0x06, 0x0c, 0x2a, 0x86, 0x48,
6050 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
6051 0x09, 0x02, 0x04, 0x02, 0x30, 0x00}},
6052 {kTestOID, "ASN1:SET", nullptr, {0x30, 0x12, 0x06, 0x0c, 0x2a, 0x86, 0x48,
6053 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
6054 0x09, 0x02, 0x04, 0x02, 0x31, 0x00}},
6055 {kTestOID, "ASN1:SEQUENCE", nullptr, {0x30, 0x12, 0x06, 0x0c, 0x2a,
6056 0x86, 0x48, 0x86, 0xf7, 0x12,
6057 0x04, 0x01, 0x84, 0xb7, 0x09,
6058 0x02, 0x04, 0x02, 0x30, 0x00}},
6059
6060 // Otherwise, they require a corresponding section in the config database
6061 // to encode values. This can be nested recursively.
6062 {kTestOID, "ASN1:SEQ:missing_confdb", nullptr, {}},
6063 {kTestOID, "ASN1:SET:missing_confdb", nullptr, {}},
6064 {kTestOID,
6065 "ASN1:SEQ:seq",
6066 R"(
6067[seq]
6068val1 = NULL
6069val2 = IA5:a
6070val3 = SET:set
6071[set]
6072# Config names do not matter, only the order.
6073val4 = INT:1
6074val3 = INT:2
6075val2 = SEQ:empty
6076val1 = INT:3
6077[empty]
6078)",
6079 {0x30, 0x24, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
6080 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x14, 0x30, 0x12,
6081 0x05, 0x00, 0x16, 0x01, 0x61, 0x31, 0x0b, 0x02, 0x01, 0x01,
6082 0x02, 0x01, 0x02, 0x02, 0x01, 0x03, 0x30, 0x00}},
6083
6084 // There is a recursion limit to stop infinite recursion.
6085 {kTestOID,
6086 "ASN1:SEQ:seq1",
6087 R"(
6088[seq1]
6089val = SEQ:seq2
6090[seq2]
6091val = SEQ:seq1
6092)",
6093 {}},
6094
6095 // Various modifiers wrap with explicit tagging or universal types.
6096 {kTestOID,
6097 "ASN1:EXP:0,EXP:16U,EXP:100A,EXP:1000C,OCTWRAP,SEQWRAP,SETWRAP,BITWRAP,"
6098 "NULL",
6099 nullptr,
6100 {0x30, 0x26, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
6101 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x16, 0xa0, 0x14,
6102 0x30, 0x12, 0x7f, 0x64, 0x0f, 0xbf, 0x87, 0x68, 0x0b, 0x04,
6103 0x09, 0x30, 0x07, 0x31, 0x05, 0x03, 0x03, 0x00, 0x05, 0x00}},
6104
6105 // Implicit tagging may also be applied to the underlying type, or the
6106 // wrapping modifiers.
6107 {kTestOID,
6108 "ASN1:IMP:1A,OCTWRAP,IMP:10,SEQWRAP,IMP:100,SETWRAP,IMP:1000,BITWRAP,"
6109 "IMP:10000,NULL",
6110 nullptr,
6111 {0x30, 0x20, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01,
6112 0x84, 0xb7, 0x09, 0x02, 0x04, 0x10, 0x41, 0x0e, 0xaa, 0x0c, 0xbf, 0x64,
6113 0x09, 0x9f, 0x87, 0x68, 0x05, 0x00, 0x9f, 0xce, 0x10, 0x00}},
6114
6115 // Implicit tagging may not be applied to explicit tagging or itself.
6116 // There's no rule against this in ASN.1, but OpenSSL does not allow it
6117 // here.
6118 {kTestOID, "ASN1:IMP:1,EXP:1,NULL", nullptr, {}},
6119 {kTestOID, "ASN1:IMP:1,IMP:1,NULL", nullptr, {}},
6120
6121 // Leading and trailing spaces on name:value pairs are removed. However,
6122 // while these pairs are delimited by commas, a type will consumes
6123 // everything after it, including commas, and spaces. So this is the
6124 // string " a, b ".
6125 {kTestOID,
6126 "ASN1: EXP:0 , IA5: a, b ",
6127 nullptr,
6128 {0x30, 0x1a, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
6129 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x0a, 0xa0, 0x08,
6130 0x16, 0x06, 0x20, 0x61, 0x2c, 0x20, 0x62, 0x20}},
6131
6132 // Modifiers without a final type.
6133 {kTestOID, "ASN1:EXP:1", nullptr, {}},
6134
6135 // Put it all together to describe a test Ed25519 key (wrapped inside an
6136 // X.509 extension).
6137 {kTestOID,
6138 "ASN1:SEQUENCE:pkcs8",
6139 R"(
6140[pkcs8]
6141vers = INT:0
6142alg = SEQWRAP,OID:1.3.101.112
6143key = FORMAT:HEX,OCTWRAP,OCT:9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
6144)",
6145 {0x30, 0x40, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
6146 0x01, 0x84, 0xb7, 0x09, 0x02, 0x04, 0x30, 0x30, 0x2e, 0x02, 0x01,
6147 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04,
6148 0x20, 0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84,
6149 0x4a, 0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69, 0x7b,
6150 0x32, 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae, 0x7f, 0x60}},
6151 };
6152 for (const auto &t : kTests) {
6153 SCOPED_TRACE(t.name);
6154 SCOPED_TRACE(t.value);
6155 SCOPED_TRACE(t.conf);
6156
6157 bssl::UniquePtr<CONF> conf;
6158 if (t.conf != nullptr) {
6159 conf.reset(NCONF_new(nullptr));
6160 ASSERT_TRUE(conf);
6161 bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(t.conf, strlen(t.conf)));
6162 ASSERT_TRUE(bio);
6163 long error_line;
6164 ASSERT_TRUE(NCONF_load_bio(conf.get(), bio.get(), &error_line))
6165 << "Failed to load config at line " << error_line;
6166 }
6167
David Benjamin114fa722022-12-30 13:37:30 -05006168 bssl::UniquePtr<X509_EXTENSION> ext(
6169 X509V3_EXT_nconf(conf.get(), nullptr, t.name, t.value));
6170 if (t.expected.empty()) {
6171 EXPECT_FALSE(ext);
6172 } else {
6173 ASSERT_TRUE(ext);
6174 uint8_t *der = nullptr;
6175 int len = i2d_X509_EXTENSION(ext.get(), &der);
6176 ASSERT_GE(len, 0);
6177 bssl::UniquePtr<uint8_t> free_der(der);
6178 EXPECT_EQ(Bytes(t.expected), Bytes(der, len));
6179 }
6180
6181 // Repeat the test with an explicit |X509V3_CTX|.
David Benjamin7c81c5f2022-12-29 14:13:24 -05006182 X509V3_CTX ctx;
6183 X509V3_set_ctx(&ctx, nullptr, nullptr, nullptr, nullptr, 0);
David Benjamin1c9d1832023-01-23 10:36:30 -05006184 X509V3_set_nconf(&ctx, conf.get());
David Benjamin114fa722022-12-30 13:37:30 -05006185 ext.reset(X509V3_EXT_nconf(conf.get(), &ctx, t.name, t.value));
David Benjamin7c81c5f2022-12-29 14:13:24 -05006186 if (t.expected.empty()) {
6187 EXPECT_FALSE(ext);
6188 } else {
6189 ASSERT_TRUE(ext);
6190 uint8_t *der = nullptr;
6191 int len = i2d_X509_EXTENSION(ext.get(), &der);
6192 ASSERT_GE(len, 0);
6193 bssl::UniquePtr<uint8_t> free_der(der);
6194 EXPECT_EQ(Bytes(t.expected), Bytes(der, len));
6195 }
6196 }
6197}