1*43723609Stb /* $OpenBSD: x509_asn1.c,v 1.21 2023/12/13 05:57:37 tb Exp $ */
26b967e81Sjob /*
36b967e81Sjob * Copyright (c) 2023 Job Snijders <job@openbsd.org>
46b967e81Sjob *
56b967e81Sjob * Permission to use, copy, modify, and distribute this software for any
66b967e81Sjob * purpose with or without fee is hereby granted, provided that the above
76b967e81Sjob * copyright notice and this permission notice appear in all copies.
86b967e81Sjob *
96b967e81Sjob * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
106b967e81Sjob * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
116b967e81Sjob * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
126b967e81Sjob * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
136b967e81Sjob * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
146b967e81Sjob * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
156b967e81Sjob * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
166b967e81Sjob */
176b967e81Sjob
186b967e81Sjob /*
196b967e81Sjob * This program tests whether the presence of "->enc.modified = 1;"
206b967e81Sjob * in select X509 setter functions properly triggers invalidation of cached
216b967e81Sjob * DER.
226b967e81Sjob */
236b967e81Sjob
246b967e81Sjob #include <err.h>
256b967e81Sjob #include <stdio.h>
266b967e81Sjob #include <string.h>
276b967e81Sjob
286b967e81Sjob #include <openssl/evp.h>
296b967e81Sjob #include <openssl/rsa.h>
306b967e81Sjob #include <openssl/x509.h>
316b967e81Sjob
32926a8368Sjob static void
x509_setup(unsigned char ** der,unsigned char ** der2,X509 ** x,long dersz,long * der2sz)33926a8368Sjob x509_setup(unsigned char **der, unsigned char **der2, X509 **x,
3460f9a609Sjob long dersz, long *der2sz)
35926a8368Sjob {
3639ee18e0Sjob const unsigned char *cpder;
3739ee18e0Sjob
3839ee18e0Sjob cpder = *der;
3939ee18e0Sjob if ((*x = d2i_X509(NULL, &cpder, dersz)) == NULL)
40926a8368Sjob errx(1, "d2i_X509");
41926a8368Sjob if ((*der2sz = i2d_X509(*x, der2)) <= 0)
42926a8368Sjob errx(1, "i2d_X509");
43926a8368Sjob }
446b967e81Sjob
45926a8368Sjob static void
x509_cleanup(X509 ** x,unsigned char ** der)46926a8368Sjob x509_cleanup(X509 **x, unsigned char **der)
47926a8368Sjob {
48926a8368Sjob X509_free(*x);
49926a8368Sjob *x = NULL;
50926a8368Sjob free(*der);
51926a8368Sjob *der = NULL;
52926a8368Sjob }
536b967e81Sjob
54926a8368Sjob static void
x509_set_integer(const char * descr,int (* f)(X509 *,ASN1_INTEGER *),X509 ** x,int i)55*43723609Stb x509_set_integer(const char *descr, int (*f)(X509 *, ASN1_INTEGER *), X509 **x,
56*43723609Stb int i)
57926a8368Sjob {
58926a8368Sjob ASN1_INTEGER *ai;
596b967e81Sjob
60926a8368Sjob if ((ai = ASN1_INTEGER_new()) == NULL)
61926a8368Sjob err(1, NULL);
62926a8368Sjob if (!ASN1_INTEGER_set(ai, i))
63926a8368Sjob errx(1, "ASN1_INTEGER_set");
640aff555dSjob if (!f(*x, ai))
65*43723609Stb errx(1, "%s: %s failed", __func__, descr);
666b967e81Sjob
67926a8368Sjob ASN1_INTEGER_free(ai);
68926a8368Sjob }
696b967e81Sjob
70926a8368Sjob static void
x509_set_name(const char * descr,int (* f)(X509 *,X509_NAME *),X509 ** x,const unsigned char * n)71*43723609Stb x509_set_name(const char *descr, int (*f)(X509 *, X509_NAME *), X509 **x,
72926a8368Sjob const unsigned char *n)
73926a8368Sjob {
74926a8368Sjob X509_NAME *xn;
756b967e81Sjob
76926a8368Sjob if ((xn = X509_NAME_new()) == NULL)
77926a8368Sjob err(1, NULL);
78926a8368Sjob if (!X509_NAME_add_entry_by_txt(xn, "C", MBSTRING_ASC, n, -1, -1, 0))
79926a8368Sjob errx(1, "X509_NAME_add_entry_by_txt");
800aff555dSjob if (!f(*x, xn))
81*43723609Stb errx(1, "%s: %s failed", __func__, descr);
82926a8368Sjob
83926a8368Sjob X509_NAME_free(xn);
84926a8368Sjob }
85926a8368Sjob
86926a8368Sjob static void
x509_set_time(const char * descr,int (* f)(X509 *,const ASN1_TIME *),X509 ** x,int t)87*43723609Stb x509_set_time(const char *descr, int (*f)(X509 *, const ASN1_TIME *), X509 **x,
88*43723609Stb int t)
89926a8368Sjob {
90926a8368Sjob ASN1_TIME *at;
91926a8368Sjob
92926a8368Sjob if ((at = X509_gmtime_adj(NULL, t)) == NULL)
93926a8368Sjob errx(1, "X509_gmtime_adj");
940aff555dSjob if (!f(*x, at))
95*43723609Stb errx(1, "%s: %s failed", __func__, descr);
96926a8368Sjob
97926a8368Sjob ASN1_TIME_free(at);
98926a8368Sjob }
996b967e81Sjob
1006b967e81Sjob static int
x509_compare(char * f,X509 * a,const unsigned char * der,long dersz)1016b967e81Sjob x509_compare(char *f, X509 *a, const unsigned char *der, long dersz)
1026b967e81Sjob {
1036b967e81Sjob unsigned char *der_test = NULL;
1046b967e81Sjob long der_testsz;
1056b967e81Sjob int rc = 0;
1066b967e81Sjob
1076b967e81Sjob if ((der_testsz = i2d_X509(a, &der_test)) <= 0)
1086b967e81Sjob errx(1, "i2d_X509");
1096b967e81Sjob
1106b967e81Sjob if (dersz == der_testsz) {
1116b967e81Sjob if (memcmp(der, der_test, dersz) == 0) {
1123dbd52dfSjob warnx("%s() stale version of encoding after i2d", f);
1136b967e81Sjob rc = 1;
1146b967e81Sjob } else
1156b967e81Sjob warnx("%s() OK", f);
1166b967e81Sjob } else
1176b967e81Sjob warnx("%s() OK", f);
1186b967e81Sjob
1196b967e81Sjob free(der_test);
1206b967e81Sjob return rc;
1216b967e81Sjob }
1226b967e81Sjob
1234962ea43Sjob static void
x509_crl_setup(unsigned char ** der,unsigned char ** der2,X509_CRL ** xc,long dersz,long * der2sz)1244962ea43Sjob x509_crl_setup(unsigned char **der, unsigned char **der2, X509_CRL **xc,
1254962ea43Sjob long dersz, long *der2sz)
1264962ea43Sjob {
1274962ea43Sjob const unsigned char *cpder;
1284962ea43Sjob
1294962ea43Sjob cpder = *der;
1304962ea43Sjob if ((*xc = d2i_X509_CRL(NULL, &cpder, dersz)) == NULL)
1314962ea43Sjob errx(1, "d2i_X509");
1324962ea43Sjob if ((*der2sz = i2d_X509_CRL(*xc, der2)) <= 0)
1334962ea43Sjob errx(1, "i2d_X509");
1344962ea43Sjob }
1354962ea43Sjob
1364962ea43Sjob static void
x509_crl_cleanup(X509_CRL ** xc,unsigned char ** der)1374962ea43Sjob x509_crl_cleanup(X509_CRL **xc, unsigned char **der)
1384962ea43Sjob {
1394962ea43Sjob X509_CRL_free(*xc);
1404962ea43Sjob *xc = NULL;
1414962ea43Sjob free(*der);
1424962ea43Sjob *der = NULL;
1434962ea43Sjob }
1444962ea43Sjob
1454962ea43Sjob static void
x509_crl_set_name(const char * descr,int (* f)(X509_CRL *,X509_NAME *),X509_CRL ** xc,const unsigned char * n)146*43723609Stb x509_crl_set_name(const char *descr, int (*f)(X509_CRL *, X509_NAME *),
147*43723609Stb X509_CRL **xc, const unsigned char *n)
1484962ea43Sjob {
1494962ea43Sjob X509_NAME *xn;
1504962ea43Sjob
1514962ea43Sjob if ((xn = X509_NAME_new()) == NULL)
1524962ea43Sjob err(1, NULL);
1534962ea43Sjob if (!X509_NAME_add_entry_by_txt(xn, "C", MBSTRING_ASC, n, -1, -1, 0))
1544962ea43Sjob errx(1, "X509_NAME_add_entry_by_txt");
1554962ea43Sjob if (!f(*xc, xn))
156*43723609Stb errx(1, "%s: %s failed", __func__, descr);
1574962ea43Sjob
1584962ea43Sjob X509_NAME_free(xn);
1594962ea43Sjob }
1604962ea43Sjob
1614962ea43Sjob static void
x509_crl_set_time(const char * descr,int (* f)(X509_CRL *,const ASN1_TIME *),X509_CRL ** xc,int t)162*43723609Stb x509_crl_set_time(const char *descr, int (*f)(X509_CRL *, const ASN1_TIME *),
163*43723609Stb X509_CRL **xc, int t)
1644962ea43Sjob {
1654962ea43Sjob ASN1_TIME *at;
1664962ea43Sjob
1674962ea43Sjob if ((at = X509_gmtime_adj(NULL, t)) == NULL)
1684962ea43Sjob errx(1, "X509_gmtime_adj");
1694962ea43Sjob if (!f(*xc, at))
170*43723609Stb errx(1, "%s: %s failed", __func__, descr);
1714962ea43Sjob
1724962ea43Sjob ASN1_TIME_free(at);
1734962ea43Sjob }
1744962ea43Sjob
1754962ea43Sjob static int
x509_crl_compare(char * f,X509_CRL * ac,const unsigned char * der,long dersz)1764962ea43Sjob x509_crl_compare(char *f, X509_CRL *ac, const unsigned char *der, long dersz)
1774962ea43Sjob {
1784962ea43Sjob unsigned char *der_test = NULL;
1794962ea43Sjob long der_testsz;
1804962ea43Sjob int rc = 0;
1814962ea43Sjob
1824962ea43Sjob if ((der_testsz = i2d_X509_CRL(ac, &der_test)) <= 0)
1834962ea43Sjob errx(1, "i2d_X509_CRL");
1844962ea43Sjob
1854962ea43Sjob if (dersz == der_testsz) {
1864962ea43Sjob if (memcmp(der, der_test, dersz) == 0) {
1873dbd52dfSjob warnx("%s() stale version of encoding after i2d", f);
1884962ea43Sjob rc = 1;
1894962ea43Sjob } else
1904962ea43Sjob warnx("%s() OK", f);
1914962ea43Sjob } else
1924962ea43Sjob warnx("%s() OK", f);
1934962ea43Sjob
1944962ea43Sjob free(der_test);
1954962ea43Sjob return rc;
1964962ea43Sjob }
1974962ea43Sjob
1984962ea43Sjob static int
test_x509_setters(void)1994962ea43Sjob test_x509_setters(void)
2006b967e81Sjob {
2016b967e81Sjob EVP_PKEY *pkey = NULL;
2026b967e81Sjob EVP_PKEY_CTX *pkey_ctx = NULL;
2036b967e81Sjob X509 *a, *x;
2046b967e81Sjob unsigned char *der = NULL, *der2 = NULL;
2056b967e81Sjob long dersz, der2sz;
2064962ea43Sjob int failed = 0;
2076b967e81Sjob
2086b967e81Sjob if ((x = X509_new()) == NULL)
2096b967e81Sjob err(1, NULL);
2106b967e81Sjob
2116b967e81Sjob if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL)
2126b967e81Sjob errx(1, "EVP_PKEY_CTX_new_id");
2136b967e81Sjob if (EVP_PKEY_keygen_init(pkey_ctx) != 1)
2146b967e81Sjob errx(1, "EVP_PKEY_keygen_init");
2156b967e81Sjob if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, 2048) <= 0)
2166b967e81Sjob errx(1, "EVP_PKEY_CTX_set_rsa_keygen_bits");
2176b967e81Sjob if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0)
2186b967e81Sjob errx(1, "EVP_PKEY_keygen");
2196b967e81Sjob if (X509_set_pubkey(x, pkey) != 1)
2206b967e81Sjob errx(1, "X509_set_pubkey");
2216b967e81Sjob
222*43723609Stb x509_set_integer("X509_set_serialNumber", X509_set_serialNumber, &x, 1);
223*43723609Stb x509_set_time("X509_set_notBefore", X509_set_notBefore, &x, 0);
224*43723609Stb x509_set_time("X509_set_notAfter", X509_set_notAfter, &x, 60);
225*43723609Stb x509_set_name("X509_set_issuer_name", X509_set_issuer_name, &x, "NL");
226*43723609Stb x509_set_name("X509_set_subject_name", X509_set_subject_name, &x, "BE");
2276b967e81Sjob
2285369d035Stb /* one time creation of the original DER */
2296b967e81Sjob if (!X509_sign(x, pkey, EVP_sha256()))
2306b967e81Sjob errx(1, "X509_sign");
2316b967e81Sjob if ((dersz = i2d_X509(x, &der)) <= 0)
2326b967e81Sjob errx(1, "i2d_X509");
2336b967e81Sjob
234926a8368Sjob /* test X509_set_version */
23560f9a609Sjob x509_setup(&der, &der2, &a, dersz, &der2sz);
2366b967e81Sjob if (!X509_set_version(a, 2))
2376b967e81Sjob errx(1, "X509_set_version");
2384962ea43Sjob failed |= x509_compare("X509_set_version", a, der2, der2sz);
239926a8368Sjob x509_cleanup(&a, &der2);
2406b967e81Sjob
241926a8368Sjob /* test X509_set_serialNumber */
24260f9a609Sjob x509_setup(&der, &der2, &a, dersz, &der2sz);
243*43723609Stb x509_set_integer("X509_set_serialNumber", X509_set_serialNumber, &a, 2);
2444962ea43Sjob failed |= x509_compare("X509_set_serialNumber", a, der2, der2sz);
245926a8368Sjob x509_cleanup(&a, &der2);
2466b967e81Sjob
247926a8368Sjob /* test X509_set_issuer_name */
24860f9a609Sjob x509_setup(&der, &der2, &a, dersz, &der2sz);
249*43723609Stb x509_set_name("X509_set_issuer_name", X509_set_issuer_name, &a, "DE");
2504962ea43Sjob failed |= x509_compare("X509_set_issuer_name", a, der2, der2sz);
251926a8368Sjob x509_cleanup(&a, &der2);
2526b967e81Sjob
253926a8368Sjob /* test X509_set_subject_name */
25460f9a609Sjob x509_setup(&der, &der2, &a, dersz, &der2sz);
255*43723609Stb x509_set_name("X509_set_subject_name", X509_set_subject_name, &a, "FR");
2564962ea43Sjob failed |= x509_compare("X509_set_subject_name", a, der2, der2sz);
257926a8368Sjob x509_cleanup(&a, &der2);
2586b967e81Sjob
259926a8368Sjob /* test X509_set_notBefore */
26060f9a609Sjob x509_setup(&der, &der2, &a, dersz, &der2sz);
261*43723609Stb x509_set_time("X509_set_notBefore", X509_set_notBefore, &a, 120);
2624962ea43Sjob failed |= x509_compare("X509_set_notBefore", a, der2, der2sz);
263926a8368Sjob x509_cleanup(&a, &der2);
2646b967e81Sjob
265926a8368Sjob /* test X509_set_notAfter */
26660f9a609Sjob x509_setup(&der, &der2, &a, dersz, &der2sz);
267*43723609Stb x509_set_time("X509_set_notAfter", X509_set_notAfter, &a, 180);
2684962ea43Sjob failed |= x509_compare("X509_set_notAfter", a, der2, der2sz);
269926a8368Sjob x509_cleanup(&a, &der2);
2706b967e81Sjob
271926a8368Sjob /* test X509_set_pubkey */
27260f9a609Sjob x509_setup(&der, &der2, &a, dersz, &der2sz);
2736b967e81Sjob if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0)
2746b967e81Sjob errx(1, "EVP_PKEY_keygen");
2756b967e81Sjob if (X509_set_pubkey(a, pkey) != 1)
2766b967e81Sjob errx(1, "X509_set_pubkey");
2775f3a4f44Sjob failed |= x509_compare("X509_set_pubkey", a, der2, der2sz);
2785f3a4f44Sjob x509_cleanup(&a, &der2);
2795f3a4f44Sjob
280926a8368Sjob EVP_PKEY_CTX_free(pkey_ctx);
281926a8368Sjob EVP_PKEY_free(pkey);
282a876585fSjob X509_free(x);
283a876585fSjob free(der);
284a876585fSjob
2854962ea43Sjob return failed;
2864962ea43Sjob }
2874962ea43Sjob
2884962ea43Sjob static int
test_x509_crl_setters(void)2894962ea43Sjob test_x509_crl_setters(void)
2904962ea43Sjob {
2914962ea43Sjob EVP_PKEY *pkey = NULL;
2924962ea43Sjob EVP_PKEY_CTX *pkey_ctx = NULL;
2934962ea43Sjob X509_CRL *ac, *xc;
2944962ea43Sjob unsigned char *der = NULL, *der2 = NULL;
2954962ea43Sjob long dersz, der2sz;
2964962ea43Sjob int failed = 0;
2974962ea43Sjob
2984962ea43Sjob if ((xc = X509_CRL_new()) == NULL)
2994962ea43Sjob err(1, NULL);
3004962ea43Sjob
3014962ea43Sjob if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL)
3024962ea43Sjob errx(1, "EVP_PKEY_CTX_new_id");
3034962ea43Sjob if (EVP_PKEY_keygen_init(pkey_ctx) != 1)
3044962ea43Sjob errx(1, "EVP_PKEY_keygen_init");
3054962ea43Sjob if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, 2048) <= 0)
3064962ea43Sjob errx(1, "EVP_PKEY_CTX_set_rsa_keygen_bits");
3074962ea43Sjob if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0)
3084962ea43Sjob errx(1, "EVP_PKEY_keygen");
3094962ea43Sjob
310*43723609Stb x509_crl_set_time("X509_CRL_set_lastUpdate", X509_CRL_set_lastUpdate,
311*43723609Stb &xc, 0);
312*43723609Stb x509_crl_set_time("X509_CRL_set_nextUpdate", X509_CRL_set_nextUpdate,
313*43723609Stb &xc, 60);
314*43723609Stb x509_crl_set_name("X509_CRL_set_issuer_name", X509_CRL_set_issuer_name,
315*43723609Stb &xc, "NL");
3164962ea43Sjob
3175369d035Stb /* one time creation of the original DER */
3184962ea43Sjob if (!X509_CRL_sign(xc, pkey, EVP_sha256()))
3194962ea43Sjob errx(1, "X509_CRL_sign");
3204962ea43Sjob if ((dersz = i2d_X509_CRL(xc, &der)) <= 0)
3214962ea43Sjob errx(1, "i2d_X509_CRL");
3224962ea43Sjob
3234962ea43Sjob /* test X509_CRL_set_version */
3244962ea43Sjob x509_crl_setup(&der, &der2, &ac, dersz, &der2sz);
3254962ea43Sjob if (!X509_CRL_set_version(ac, 1))
3264962ea43Sjob errx(1, "X509_CRL_set_version");
3274962ea43Sjob failed |= x509_crl_compare("X509_CRL_set_version", ac, der2, der2sz);
3284962ea43Sjob x509_crl_cleanup(&ac, &der2);
3294962ea43Sjob
3304962ea43Sjob /* test X509_CRL_set_issuer_name */
3314962ea43Sjob x509_crl_setup(&der, &der2, &ac, dersz, &der2sz);
332*43723609Stb x509_crl_set_name("X509_CRL_set_issuer_name", X509_CRL_set_issuer_name,
333*43723609Stb &ac, "DE");
3344962ea43Sjob failed |= x509_crl_compare("X509_CRL_set_issuer_name", ac, der2,
3354962ea43Sjob der2sz);
3364962ea43Sjob x509_crl_cleanup(&ac, &der2);
3374962ea43Sjob
3384962ea43Sjob /* test X509_CRL_set_lastUpdate */
3394962ea43Sjob x509_crl_setup(&der, &der2, &ac, dersz, &der2sz);
340*43723609Stb x509_crl_set_time("X509_CRL_set_lastUpdate", X509_CRL_set_lastUpdate,
341*43723609Stb &ac, 120);
34217feaa75Sjob failed |= x509_crl_compare("X509_CRL_set_lastUpdate", ac, der2, der2sz);
3434962ea43Sjob x509_crl_cleanup(&ac, &der2);
3444962ea43Sjob
3454962ea43Sjob /* test X509_CRL_set_nextUpdate */
3464962ea43Sjob x509_crl_setup(&der, &der2, &ac, dersz, &der2sz);
347*43723609Stb x509_crl_set_time("X509_CRL_set_nextUpdate", X509_CRL_set_nextUpdate,
348*43723609Stb &ac, 180);
34917feaa75Sjob failed |= x509_crl_compare("X509_CRL_set_nextUpdate", ac, der2, der2sz);
3504962ea43Sjob x509_crl_cleanup(&ac, &der2);
3514962ea43Sjob
3525f3a4f44Sjob EVP_PKEY_free(pkey);
3535f3a4f44Sjob EVP_PKEY_CTX_free(pkey_ctx);
3544962ea43Sjob X509_CRL_free(xc);
3554962ea43Sjob free(der);
3564962ea43Sjob
3574962ea43Sjob return failed;
3584962ea43Sjob }
3594962ea43Sjob
360a4301a11Sjob static void
x509_req_setup(unsigned char ** der,unsigned char ** der2,X509_REQ ** xr,long dersz,long * der2sz)361a4301a11Sjob x509_req_setup(unsigned char **der, unsigned char **der2, X509_REQ **xr,
362a4301a11Sjob long dersz, long *der2sz)
363a4301a11Sjob {
364a4301a11Sjob const unsigned char *cpder;
365a4301a11Sjob
366a4301a11Sjob cpder = *der;
367a4301a11Sjob if ((*xr = d2i_X509_REQ(NULL, &cpder, dersz)) == NULL)
368a4301a11Sjob errx(1, "d2i_X509");
369a4301a11Sjob if ((*der2sz = i2d_X509_REQ(*xr, der2)) <= 0)
370a4301a11Sjob errx(1, "i2d_X509");
371a4301a11Sjob }
372a4301a11Sjob
373a4301a11Sjob static int
x509_req_compare(char * f,X509_REQ * xr,const unsigned char * der,long dersz)374a4301a11Sjob x509_req_compare(char *f, X509_REQ *xr, const unsigned char *der, long dersz)
375a4301a11Sjob {
376a4301a11Sjob unsigned char *der_test = NULL;
377a4301a11Sjob long der_testsz;
378a4301a11Sjob int rc = 0;
379a4301a11Sjob
380a4301a11Sjob if ((der_testsz = i2d_X509_REQ(xr, &der_test)) <= 0)
381a4301a11Sjob errx(1, "i2d_X509_REQ");
382a4301a11Sjob
383a4301a11Sjob if (dersz == der_testsz) {
384a4301a11Sjob if (memcmp(der, der_test, dersz) == 0) {
3853dbd52dfSjob warnx("%s() stale version of encoding after i2d", f);
386a4301a11Sjob rc = 1;
387a4301a11Sjob } else
388a4301a11Sjob warnx("%s() OK", f);
389a4301a11Sjob } else
390a4301a11Sjob warnx("%s() OK", f);
391a4301a11Sjob
392a4301a11Sjob free(der_test);
393a4301a11Sjob return rc;
394a4301a11Sjob }
395a4301a11Sjob
396a4301a11Sjob static void
x509_req_cleanup(X509_REQ ** xr,unsigned char ** der)397a4301a11Sjob x509_req_cleanup(X509_REQ **xr, unsigned char **der)
398a4301a11Sjob {
399a4301a11Sjob X509_REQ_free(*xr);
400a4301a11Sjob *xr = NULL;
401a4301a11Sjob free(*der);
402a4301a11Sjob *der = NULL;
403a4301a11Sjob }
404a4301a11Sjob
405a4301a11Sjob static int
test_x509_req_setters(void)406a4301a11Sjob test_x509_req_setters(void)
407a4301a11Sjob {
408a4301a11Sjob EVP_PKEY *pkey = NULL;
409a4301a11Sjob EVP_PKEY_CTX *pkey_ctx = NULL;
410a4301a11Sjob X509_REQ *ar = NULL, *xr = NULL;
411a4301a11Sjob unsigned char *der = NULL, *der2 = NULL;
412a4301a11Sjob X509_NAME *xn;
413a4301a11Sjob ASN1_OCTET_STRING *aos;
414a4301a11Sjob X509_EXTENSION *xe;
415a4301a11Sjob STACK_OF(X509_EXTENSION) *exts = NULL;
416a4301a11Sjob ASN1_OBJECT *coid;
417a4301a11Sjob X509_ATTRIBUTE *xa;
418a4301a11Sjob long dersz, der2sz;
419a4301a11Sjob int failed = 0;
420a4301a11Sjob
421a4301a11Sjob if ((xr = X509_REQ_new()) == NULL)
422a4301a11Sjob err(1, NULL);
423a4301a11Sjob
424a4301a11Sjob if (!X509_REQ_set_version(xr, 0))
425a4301a11Sjob errx(1, "X509_REQ_set_version");
426a4301a11Sjob
427a4301a11Sjob if ((xn = X509_NAME_new()) == NULL)
428a4301a11Sjob err(1, NULL);
429a4301a11Sjob if (!X509_NAME_add_entry_by_txt(xn, "C", MBSTRING_ASC, "NL", -1, -1, 0))
430a4301a11Sjob errx(1, "X509_NAME_add_entry_by_txt");
431a4301a11Sjob if (!X509_REQ_set_subject_name(xr, xn))
432a4301a11Sjob errx(1, "X509_REQ_set_subject_name");
433a4301a11Sjob
434a4301a11Sjob if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL)
435a4301a11Sjob errx(1, "EVP_PKEY_CTX_new_id");
436a4301a11Sjob if (EVP_PKEY_keygen_init(pkey_ctx) != 1)
437a4301a11Sjob errx(1, "EVP_PKEY_keygen_init");
438a4301a11Sjob if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, 2048) <= 0)
439a4301a11Sjob errx(1, "EVP_PKEY_CTX_set_rsa_keygen_bits");
440a4301a11Sjob if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0)
441a4301a11Sjob errx(1, "EVP_PKEY_keygen");
442a4301a11Sjob if (!X509_REQ_set_pubkey(xr, pkey))
443a4301a11Sjob errx(1, "X509_REQ_set_pubkey");
444a4301a11Sjob
445a4301a11Sjob if (!X509_REQ_sign(xr, pkey, EVP_sha256()))
446a4301a11Sjob errx(1, "X509_REQ_sign");
447a4301a11Sjob if ((dersz = i2d_X509_REQ(xr, &der)) <= 0)
448a4301a11Sjob errx(1, "i2d_X509_REQ");
449a4301a11Sjob
450a4301a11Sjob /* test X509_REQ_add_extensions */
451a4301a11Sjob x509_req_setup(&der, &der2, &ar, dersz, &der2sz);
452a4301a11Sjob if ((aos = ASN1_OCTET_STRING_new()) == NULL)
453a4301a11Sjob err(1, NULL);
454a4301a11Sjob ASN1_OCTET_STRING_set(aos, (unsigned char *)"DNS: test.nl",
455a4301a11Sjob strlen("DNS: test.nl"));
456a4301a11Sjob if ((xe = X509_EXTENSION_new()) == NULL)
457a4301a11Sjob err(1, NULL);
458a4301a11Sjob if (!X509_EXTENSION_create_by_NID(&xe, NID_subject_alt_name, 0, aos))
459a4301a11Sjob errx(1, "X509_EXTENSION_create_by_NID");
460a4301a11Sjob if ((exts = sk_X509_EXTENSION_new_null()) == NULL)
461a4301a11Sjob errx(1, "sk_X509_EXTENSION_new_null");
462a4301a11Sjob sk_X509_EXTENSION_push(exts, xe);
463a4301a11Sjob if (!X509_REQ_add_extensions(ar, exts))
464a4301a11Sjob errx(1, "X509_REQ_add_extensions");
465a4301a11Sjob failed |= x509_req_compare("X509_REQ_add_extensions", ar, der2, der2sz);
466a4301a11Sjob x509_req_cleanup(&ar, &der2);
467a4301a11Sjob
468a4301a11Sjob /* test X509_REQ_add1_attr */
469a4301a11Sjob x509_req_setup(&der, &der2, &ar, dersz, &der2sz);
470a4301a11Sjob if ((coid = OBJ_nid2obj(NID_pkcs7_data)) == NULL)
471a4301a11Sjob errx(1, "OBJ_nid2obj");
472a4301a11Sjob if ((xa = X509_ATTRIBUTE_create(NID_pkcs9_contentType, V_ASN1_OBJECT,
473a4301a11Sjob coid)) == NULL)
474a4301a11Sjob errx(1, "X509_ATTRIBUTE_create");
475a4301a11Sjob if (!X509_REQ_add1_attr(ar, xa))
476a4301a11Sjob errx(1, "X509_REQ_add1_attr");
477a4301a11Sjob failed |= x509_req_compare("X509_REQ_add1_attr", ar, der2, der2sz);
478a4301a11Sjob x509_req_cleanup(&ar, &der2);
479a4301a11Sjob
4805f3a4f44Sjob ASN1_OBJECT_free(coid);
4815f3a4f44Sjob X509_NAME_free(xn);
482a4301a11Sjob ASN1_OCTET_STRING_free(aos);
4835f3a4f44Sjob sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
484a4301a11Sjob X509_ATTRIBUTE_free(xa);
485a4301a11Sjob EVP_PKEY_free(pkey);
486a4301a11Sjob EVP_PKEY_CTX_free(pkey_ctx);
487a4301a11Sjob X509_REQ_free(xr);
488a4301a11Sjob free(der);
489a4301a11Sjob
490a4301a11Sjob return failed;
491a4301a11Sjob }
492a4301a11Sjob
493f5d1ae50Sbeck static const struct testcase {
494f5d1ae50Sbeck char *data;
495f5d1ae50Sbeck int len;
496f5d1ae50Sbeck int len_to_pass;
497f5d1ae50Sbeck int encode_type;
498f5d1ae50Sbeck int expected_result;
499f5d1ae50Sbeck char *expected_string;
500f5d1ae50Sbeck } testCases[] = {
501f5d1ae50Sbeck /* should work */
502f5d1ae50Sbeck {"fozzie", 6, 80, MBSTRING_ASC, 6, "fozzie"},
503f5d1ae50Sbeck /* should work */
504f5d1ae50Sbeck {"fozzie", 6, -1, MBSTRING_ASC, 6, ""},
505f5d1ae50Sbeck /* should fail, truncation */
506f5d1ae50Sbeck {"muppet", 6, 5, MBSTRING_ASC, -1, ""},
507f5d1ae50Sbeck /* should fail, contains 0 byte */
508f5d1ae50Sbeck {"g\0nzo", 5, 80, MBSTRING_ASC, -1, ""},
509f5d1ae50Sbeck /* should fail, can't encode as utf-8 */
510f5d1ae50Sbeck {"\x30\x00", 2, 80, V_ASN1_SEQUENCE, -1, ""},
511f5d1ae50Sbeck };
512f5d1ae50Sbeck
513f5d1ae50Sbeck #define NUM_TEST_CASES (sizeof(testCases) / sizeof(testCases[0]))
514f5d1ae50Sbeck
515f5d1ae50Sbeck static int
test_x509_name_get(void)516f5d1ae50Sbeck test_x509_name_get(void)
517f5d1ae50Sbeck {
518f5d1ae50Sbeck int failed = 0;
519f5d1ae50Sbeck size_t i;
520f5d1ae50Sbeck
521f5d1ae50Sbeck for (i = 0; i < NUM_TEST_CASES; i++) {
522f5d1ae50Sbeck const struct testcase *test = testCases + i;
523f5d1ae50Sbeck X509_NAME_ENTRY *entry = NULL;
524f5d1ae50Sbeck X509_NAME *name = NULL;
525f5d1ae50Sbeck char textbuf[80];
526f5d1ae50Sbeck int result;
527f5d1ae50Sbeck
528f5d1ae50Sbeck textbuf[0] = '\0';
529f5d1ae50Sbeck if ((name = X509_NAME_new()) == NULL)
530f5d1ae50Sbeck err(1, "X509_NAME_new");
531f5d1ae50Sbeck if ((entry = X509_NAME_ENTRY_new()) == NULL)
532f5d1ae50Sbeck err(1, "X509_NAME_ENTRY_new");
533f5d1ae50Sbeck if (!X509_NAME_ENTRY_set_object(entry,
534f5d1ae50Sbeck OBJ_nid2obj(NID_commonName)))
535f5d1ae50Sbeck err(1, "X509_NAME_ENTRY_set_object");
536f5d1ae50Sbeck if (!X509_NAME_ENTRY_set_data(entry, test->encode_type,
537f5d1ae50Sbeck test->data, test->len))
538f5d1ae50Sbeck err(1, "X509_NAME_ENTRY_set_data");
539f5d1ae50Sbeck if (!X509_NAME_add_entry(name, entry, -1, 0))
540f5d1ae50Sbeck err(1, "X509_NAME_add_entry");
541f5d1ae50Sbeck if (test->len_to_pass == -1)
542f5d1ae50Sbeck result = X509_NAME_get_text_by_NID(name, NID_commonName,
543f5d1ae50Sbeck NULL, 0);
544f5d1ae50Sbeck else
545f5d1ae50Sbeck result = X509_NAME_get_text_by_NID(name, NID_commonName,
546f5d1ae50Sbeck textbuf, test->len_to_pass);
547f5d1ae50Sbeck if (result != test->expected_result) {
548f5d1ae50Sbeck fprintf(stderr,
549f5d1ae50Sbeck "Test %zu X509_GET_text_by_NID returned %d,"
550f5d1ae50Sbeck "expected %d\n", i, result, test->expected_result);
551f5d1ae50Sbeck failed++;
552f5d1ae50Sbeck }
553f5d1ae50Sbeck if (result != -1 &&
554f5d1ae50Sbeck strcmp(test->expected_string, textbuf) != 0) {
555f5d1ae50Sbeck fprintf(stderr,
556f5d1ae50Sbeck "Test %zu, X509_GET_text_by_NID returned bytes do"
557f5d1ae50Sbeck "not match \n", i);
558f5d1ae50Sbeck failed++;
559f5d1ae50Sbeck }
560f5d1ae50Sbeck X509_NAME_ENTRY_free(entry);
561f5d1ae50Sbeck X509_NAME_free(name);
562f5d1ae50Sbeck }
563f5d1ae50Sbeck return failed;
564f5d1ae50Sbeck }
565f5d1ae50Sbeck
566f5d1ae50Sbeck int
main(void)567f5d1ae50Sbeck main(void)
5684962ea43Sjob {
5694962ea43Sjob int failed = 0;
5704962ea43Sjob
5714962ea43Sjob failed |= test_x509_setters();
5725369d035Stb /* failed |= */ test_x509_crl_setters();
5735369d035Stb /* failed |= */ test_x509_req_setters();
574f5d1ae50Sbeck failed |= test_x509_name_get();
5754962ea43Sjob
576b0c62589Sjob OPENSSL_cleanup();
577b0c62589Sjob
5784962ea43Sjob return failed;
5796b967e81Sjob }
580