xref: /freebsd/crypto/openssl/crypto/x509/x_x509.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1e71b7053SJung-uk Kim /*
2*b077aed3SPierre Pronchery  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
8e71b7053SJung-uk Kim  */
9e71b7053SJung-uk Kim 
10e71b7053SJung-uk Kim #include <stdio.h>
11e71b7053SJung-uk Kim #include "internal/cryptlib.h"
12e71b7053SJung-uk Kim #include <openssl/evp.h>
13e71b7053SJung-uk Kim #include <openssl/asn1t.h>
14e71b7053SJung-uk Kim #include <openssl/x509.h>
15e71b7053SJung-uk Kim #include <openssl/x509v3.h>
1617f01e99SJung-uk Kim #include "crypto/x509.h"
17e71b7053SJung-uk Kim 
18e71b7053SJung-uk Kim ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
19e71b7053SJung-uk Kim         ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
20e71b7053SJung-uk Kim         ASN1_EMBED(X509_CINF, serialNumber, ASN1_INTEGER),
21e71b7053SJung-uk Kim         ASN1_EMBED(X509_CINF, signature, X509_ALGOR),
22e71b7053SJung-uk Kim         ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
23e71b7053SJung-uk Kim         ASN1_EMBED(X509_CINF, validity, X509_VAL),
24e71b7053SJung-uk Kim         ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
25e71b7053SJung-uk Kim         ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
26e71b7053SJung-uk Kim         ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
27e71b7053SJung-uk Kim         ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
28e71b7053SJung-uk Kim         ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
29e71b7053SJung-uk Kim } ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)
30e71b7053SJung-uk Kim 
31e71b7053SJung-uk Kim IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
32e71b7053SJung-uk Kim /* X509 top level structure needs a bit of customisation */
33e71b7053SJung-uk Kim 
34*b077aed3SPierre Pronchery extern void ossl_policy_cache_free(X509_POLICY_CACHE *cache);
35e71b7053SJung-uk Kim 
x509_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)36e71b7053SJung-uk Kim static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
37e71b7053SJung-uk Kim                    void *exarg)
38e71b7053SJung-uk Kim {
39e71b7053SJung-uk Kim     X509 *ret = (X509 *)*pval;
40e71b7053SJung-uk Kim 
41e71b7053SJung-uk Kim     switch (operation) {
42e71b7053SJung-uk Kim 
436935a639SJung-uk Kim     case ASN1_OP_D2I_PRE:
446935a639SJung-uk Kim         CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
456935a639SJung-uk Kim         X509_CERT_AUX_free(ret->aux);
466935a639SJung-uk Kim         ASN1_OCTET_STRING_free(ret->skid);
476935a639SJung-uk Kim         AUTHORITY_KEYID_free(ret->akid);
486935a639SJung-uk Kim         CRL_DIST_POINTS_free(ret->crldp);
49*b077aed3SPierre Pronchery         ossl_policy_cache_free(ret->policy_cache);
506935a639SJung-uk Kim         GENERAL_NAMES_free(ret->altname);
516935a639SJung-uk Kim         NAME_CONSTRAINTS_free(ret->nc);
526935a639SJung-uk Kim #ifndef OPENSSL_NO_RFC3779
536935a639SJung-uk Kim         sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
546935a639SJung-uk Kim         ASIdentifiers_free(ret->rfc3779_asid);
556935a639SJung-uk Kim #endif
56*b077aed3SPierre Pronchery         ASN1_OCTET_STRING_free(ret->distinguishing_id);
576935a639SJung-uk Kim 
586935a639SJung-uk Kim         /* fall thru */
596935a639SJung-uk Kim 
60e71b7053SJung-uk Kim     case ASN1_OP_NEW_POST:
616935a639SJung-uk Kim         ret->ex_cached = 0;
626935a639SJung-uk Kim         ret->ex_kusage = 0;
636935a639SJung-uk Kim         ret->ex_xkusage = 0;
646935a639SJung-uk Kim         ret->ex_nscert = 0;
65e71b7053SJung-uk Kim         ret->ex_flags = 0;
66e71b7053SJung-uk Kim         ret->ex_pathlen = -1;
67e71b7053SJung-uk Kim         ret->ex_pcpathlen = -1;
68e71b7053SJung-uk Kim         ret->skid = NULL;
69e71b7053SJung-uk Kim         ret->akid = NULL;
706935a639SJung-uk Kim         ret->policy_cache = NULL;
716935a639SJung-uk Kim         ret->altname = NULL;
726935a639SJung-uk Kim         ret->nc = NULL;
73e71b7053SJung-uk Kim #ifndef OPENSSL_NO_RFC3779
74e71b7053SJung-uk Kim         ret->rfc3779_addr = NULL;
75e71b7053SJung-uk Kim         ret->rfc3779_asid = NULL;
76e71b7053SJung-uk Kim #endif
77*b077aed3SPierre Pronchery         ret->distinguishing_id = NULL;
78e71b7053SJung-uk Kim         ret->aux = NULL;
79e71b7053SJung-uk Kim         ret->crldp = NULL;
80e71b7053SJung-uk Kim         if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data))
81e71b7053SJung-uk Kim             return 0;
82e71b7053SJung-uk Kim         break;
83e71b7053SJung-uk Kim 
84e71b7053SJung-uk Kim     case ASN1_OP_FREE_POST:
85e71b7053SJung-uk Kim         CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
86e71b7053SJung-uk Kim         X509_CERT_AUX_free(ret->aux);
87e71b7053SJung-uk Kim         ASN1_OCTET_STRING_free(ret->skid);
88e71b7053SJung-uk Kim         AUTHORITY_KEYID_free(ret->akid);
89e71b7053SJung-uk Kim         CRL_DIST_POINTS_free(ret->crldp);
90*b077aed3SPierre Pronchery         ossl_policy_cache_free(ret->policy_cache);
91e71b7053SJung-uk Kim         GENERAL_NAMES_free(ret->altname);
92e71b7053SJung-uk Kim         NAME_CONSTRAINTS_free(ret->nc);
93e71b7053SJung-uk Kim #ifndef OPENSSL_NO_RFC3779
94e71b7053SJung-uk Kim         sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
95e71b7053SJung-uk Kim         ASIdentifiers_free(ret->rfc3779_asid);
96e71b7053SJung-uk Kim #endif
97*b077aed3SPierre Pronchery         ASN1_OCTET_STRING_free(ret->distinguishing_id);
98*b077aed3SPierre Pronchery         OPENSSL_free(ret->propq);
99e71b7053SJung-uk Kim         break;
100e71b7053SJung-uk Kim 
101*b077aed3SPierre Pronchery     case ASN1_OP_DUP_POST:
102*b077aed3SPierre Pronchery         {
103*b077aed3SPierre Pronchery             X509 *old = exarg;
104*b077aed3SPierre Pronchery 
105*b077aed3SPierre Pronchery             if (!ossl_x509_set0_libctx(ret, old->libctx, old->propq))
106*b077aed3SPierre Pronchery                 return 0;
107*b077aed3SPierre Pronchery         }
108*b077aed3SPierre Pronchery         break;
109*b077aed3SPierre Pronchery     case ASN1_OP_GET0_LIBCTX:
110*b077aed3SPierre Pronchery         {
111*b077aed3SPierre Pronchery             OSSL_LIB_CTX **libctx = exarg;
112*b077aed3SPierre Pronchery 
113*b077aed3SPierre Pronchery             *libctx = ret->libctx;
114*b077aed3SPierre Pronchery         }
115*b077aed3SPierre Pronchery         break;
116*b077aed3SPierre Pronchery 
117*b077aed3SPierre Pronchery     case ASN1_OP_GET0_PROPQ:
118*b077aed3SPierre Pronchery         {
119*b077aed3SPierre Pronchery             const char **propq = exarg;
120*b077aed3SPierre Pronchery 
121*b077aed3SPierre Pronchery             *propq = ret->propq;
122*b077aed3SPierre Pronchery         }
123*b077aed3SPierre Pronchery         break;
124*b077aed3SPierre Pronchery 
125*b077aed3SPierre Pronchery     default:
126*b077aed3SPierre Pronchery         break;
127e71b7053SJung-uk Kim     }
128e71b7053SJung-uk Kim 
129e71b7053SJung-uk Kim     return 1;
130e71b7053SJung-uk Kim }
131e71b7053SJung-uk Kim 
132e71b7053SJung-uk Kim ASN1_SEQUENCE_ref(X509, x509_cb) = {
133e71b7053SJung-uk Kim         ASN1_EMBED(X509, cert_info, X509_CINF),
134e71b7053SJung-uk Kim         ASN1_EMBED(X509, sig_alg, X509_ALGOR),
135e71b7053SJung-uk Kim         ASN1_EMBED(X509, signature, ASN1_BIT_STRING)
136e71b7053SJung-uk Kim } ASN1_SEQUENCE_END_ref(X509, X509)
137e71b7053SJung-uk Kim 
138e71b7053SJung-uk Kim IMPLEMENT_ASN1_FUNCTIONS(X509)
139e71b7053SJung-uk Kim IMPLEMENT_ASN1_DUP_FUNCTION(X509)
140e71b7053SJung-uk Kim 
141*b077aed3SPierre Pronchery /*
142*b077aed3SPierre Pronchery  * This should only be used if the X509 object was embedded inside another
143*b077aed3SPierre Pronchery  * asn1 object and it needs a libctx to operate.
144*b077aed3SPierre Pronchery  * Use X509_new_ex() instead if possible.
145*b077aed3SPierre Pronchery  */
146*b077aed3SPierre Pronchery int ossl_x509_set0_libctx(X509 *x, OSSL_LIB_CTX *libctx, const char *propq)
147*b077aed3SPierre Pronchery {
148*b077aed3SPierre Pronchery     if (x != NULL) {
149*b077aed3SPierre Pronchery         x->libctx = libctx;
150*b077aed3SPierre Pronchery         OPENSSL_free(x->propq);
151*b077aed3SPierre Pronchery         x->propq = NULL;
152*b077aed3SPierre Pronchery         if (propq != NULL) {
153*b077aed3SPierre Pronchery             x->propq = OPENSSL_strdup(propq);
154*b077aed3SPierre Pronchery             if (x->propq == NULL)
155*b077aed3SPierre Pronchery                 return 0;
156*b077aed3SPierre Pronchery         }
157*b077aed3SPierre Pronchery     }
158*b077aed3SPierre Pronchery     return 1;
159*b077aed3SPierre Pronchery }
160*b077aed3SPierre Pronchery 
X509_new_ex(OSSL_LIB_CTX * libctx,const char * propq)161*b077aed3SPierre Pronchery X509 *X509_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
162*b077aed3SPierre Pronchery {
163*b077aed3SPierre Pronchery     X509 *cert = NULL;
164*b077aed3SPierre Pronchery 
165*b077aed3SPierre Pronchery     cert = (X509 *)ASN1_item_new_ex(X509_it(), libctx, propq);
166*b077aed3SPierre Pronchery     if (!ossl_x509_set0_libctx(cert, libctx, propq)) {
167*b077aed3SPierre Pronchery         X509_free(cert);
168*b077aed3SPierre Pronchery         cert = NULL;
169*b077aed3SPierre Pronchery     }
170*b077aed3SPierre Pronchery     return cert;
171*b077aed3SPierre Pronchery }
172*b077aed3SPierre Pronchery 
X509_set_ex_data(X509 * r,int idx,void * arg)173e71b7053SJung-uk Kim int X509_set_ex_data(X509 *r, int idx, void *arg)
174e71b7053SJung-uk Kim {
175e71b7053SJung-uk Kim     return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
176e71b7053SJung-uk Kim }
177e71b7053SJung-uk Kim 
X509_get_ex_data(const X509 * r,int idx)178*b077aed3SPierre Pronchery void *X509_get_ex_data(const X509 *r, int idx)
179e71b7053SJung-uk Kim {
180e71b7053SJung-uk Kim     return CRYPTO_get_ex_data(&r->ex_data, idx);
181e71b7053SJung-uk Kim }
182e71b7053SJung-uk Kim 
183e71b7053SJung-uk Kim /*
184e71b7053SJung-uk Kim  * X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with
185e71b7053SJung-uk Kim  * extra info tagged on the end. Since these functions set how a certificate
186e71b7053SJung-uk Kim  * is trusted they should only be used when the certificate comes from a
187e71b7053SJung-uk Kim  * reliable source such as local storage.
188e71b7053SJung-uk Kim  */
189e71b7053SJung-uk Kim 
d2i_X509_AUX(X509 ** a,const unsigned char ** pp,long length)190e71b7053SJung-uk Kim X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
191e71b7053SJung-uk Kim {
192e71b7053SJung-uk Kim     const unsigned char *q;
193e71b7053SJung-uk Kim     X509 *ret;
194e71b7053SJung-uk Kim     int freeret = 0;
195e71b7053SJung-uk Kim 
196e71b7053SJung-uk Kim     /* Save start position */
197e71b7053SJung-uk Kim     q = *pp;
198e71b7053SJung-uk Kim 
199e71b7053SJung-uk Kim     if (a == NULL || *a == NULL)
200e71b7053SJung-uk Kim         freeret = 1;
201e71b7053SJung-uk Kim     ret = d2i_X509(a, &q, length);
202e71b7053SJung-uk Kim     /* If certificate unreadable then forget it */
203e71b7053SJung-uk Kim     if (ret == NULL)
204e71b7053SJung-uk Kim         return NULL;
205e71b7053SJung-uk Kim     /* update length */
206e71b7053SJung-uk Kim     length -= q - *pp;
207e71b7053SJung-uk Kim     if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length))
208e71b7053SJung-uk Kim         goto err;
209e71b7053SJung-uk Kim     *pp = q;
210e71b7053SJung-uk Kim     return ret;
211e71b7053SJung-uk Kim  err:
212e71b7053SJung-uk Kim     if (freeret) {
213e71b7053SJung-uk Kim         X509_free(ret);
214e71b7053SJung-uk Kim         if (a)
215e71b7053SJung-uk Kim             *a = NULL;
216e71b7053SJung-uk Kim     }
217e71b7053SJung-uk Kim     return NULL;
218e71b7053SJung-uk Kim }
219e71b7053SJung-uk Kim 
220e71b7053SJung-uk Kim /*
221e71b7053SJung-uk Kim  * Serialize trusted certificate to *pp or just return the required buffer
222e71b7053SJung-uk Kim  * length if pp == NULL.  We ultimately want to avoid modifying *pp in the
223e71b7053SJung-uk Kim  * error path, but that depends on similar hygiene in lower-level functions.
224e71b7053SJung-uk Kim  * Here we avoid compounding the problem.
225e71b7053SJung-uk Kim  */
i2d_x509_aux_internal(const X509 * a,unsigned char ** pp)226*b077aed3SPierre Pronchery static int i2d_x509_aux_internal(const X509 *a, unsigned char **pp)
227e71b7053SJung-uk Kim {
228e71b7053SJung-uk Kim     int length, tmplen;
229e71b7053SJung-uk Kim     unsigned char *start = pp != NULL ? *pp : NULL;
230e71b7053SJung-uk Kim 
231e71b7053SJung-uk Kim     /*
232e71b7053SJung-uk Kim      * This might perturb *pp on error, but fixing that belongs in i2d_X509()
233e71b7053SJung-uk Kim      * not here.  It should be that if a == NULL length is zero, but we check
234e71b7053SJung-uk Kim      * both just in case.
235e71b7053SJung-uk Kim      */
236e71b7053SJung-uk Kim     length = i2d_X509(a, pp);
237e71b7053SJung-uk Kim     if (length <= 0 || a == NULL)
238e71b7053SJung-uk Kim         return length;
239e71b7053SJung-uk Kim 
240e71b7053SJung-uk Kim     tmplen = i2d_X509_CERT_AUX(a->aux, pp);
241e71b7053SJung-uk Kim     if (tmplen < 0) {
242e71b7053SJung-uk Kim         if (start != NULL)
243e71b7053SJung-uk Kim             *pp = start;
244e71b7053SJung-uk Kim         return tmplen;
245e71b7053SJung-uk Kim     }
246e71b7053SJung-uk Kim     length += tmplen;
247e71b7053SJung-uk Kim 
248e71b7053SJung-uk Kim     return length;
249e71b7053SJung-uk Kim }
250e71b7053SJung-uk Kim 
251e71b7053SJung-uk Kim /*
252e71b7053SJung-uk Kim  * Serialize trusted certificate to *pp, or just return the required buffer
253e71b7053SJung-uk Kim  * length if pp == NULL.
254e71b7053SJung-uk Kim  *
255e71b7053SJung-uk Kim  * When pp is not NULL, but *pp == NULL, we allocate the buffer, but since
256e71b7053SJung-uk Kim  * we're writing two ASN.1 objects back to back, we can't have i2d_X509() do
257e71b7053SJung-uk Kim  * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the
258e71b7053SJung-uk Kim  * allocated buffer.
259e71b7053SJung-uk Kim  */
i2d_X509_AUX(const X509 * a,unsigned char ** pp)260*b077aed3SPierre Pronchery int i2d_X509_AUX(const X509 *a, unsigned char **pp)
261e71b7053SJung-uk Kim {
262e71b7053SJung-uk Kim     int length;
263e71b7053SJung-uk Kim     unsigned char *tmp;
264e71b7053SJung-uk Kim 
265e71b7053SJung-uk Kim     /* Buffer provided by caller */
266e71b7053SJung-uk Kim     if (pp == NULL || *pp != NULL)
267e71b7053SJung-uk Kim         return i2d_x509_aux_internal(a, pp);
268e71b7053SJung-uk Kim 
269e71b7053SJung-uk Kim     /* Obtain the combined length */
270e71b7053SJung-uk Kim     if ((length = i2d_x509_aux_internal(a, NULL)) <= 0)
271e71b7053SJung-uk Kim         return length;
272e71b7053SJung-uk Kim 
273e71b7053SJung-uk Kim     /* Allocate requisite combined storage */
274e71b7053SJung-uk Kim     *pp = tmp = OPENSSL_malloc(length);
275e71b7053SJung-uk Kim     if (tmp == NULL) {
276*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
277e71b7053SJung-uk Kim         return -1;
278e71b7053SJung-uk Kim     }
279e71b7053SJung-uk Kim 
280e71b7053SJung-uk Kim     /* Encode, but keep *pp at the originally malloced pointer */
281e71b7053SJung-uk Kim     length = i2d_x509_aux_internal(a, &tmp);
282e71b7053SJung-uk Kim     if (length <= 0) {
283e71b7053SJung-uk Kim         OPENSSL_free(*pp);
284e71b7053SJung-uk Kim         *pp = NULL;
285e71b7053SJung-uk Kim     }
286e71b7053SJung-uk Kim     return length;
287e71b7053SJung-uk Kim }
288e71b7053SJung-uk Kim 
i2d_re_X509_tbs(X509 * x,unsigned char ** pp)289e71b7053SJung-uk Kim int i2d_re_X509_tbs(X509 *x, unsigned char **pp)
290e71b7053SJung-uk Kim {
291e71b7053SJung-uk Kim     x->cert_info.enc.modified = 1;
292e71b7053SJung-uk Kim     return i2d_X509_CINF(&x->cert_info, pp);
293e71b7053SJung-uk Kim }
294e71b7053SJung-uk Kim 
X509_get0_signature(const ASN1_BIT_STRING ** psig,const X509_ALGOR ** palg,const X509 * x)295e71b7053SJung-uk Kim void X509_get0_signature(const ASN1_BIT_STRING **psig,
296e71b7053SJung-uk Kim                          const X509_ALGOR **palg, const X509 *x)
297e71b7053SJung-uk Kim {
298e71b7053SJung-uk Kim     if (psig)
299e71b7053SJung-uk Kim         *psig = &x->signature;
300e71b7053SJung-uk Kim     if (palg)
301e71b7053SJung-uk Kim         *palg = &x->sig_alg;
302e71b7053SJung-uk Kim }
303e71b7053SJung-uk Kim 
X509_get_signature_nid(const X509 * x)304e71b7053SJung-uk Kim int X509_get_signature_nid(const X509 *x)
305e71b7053SJung-uk Kim {
306e71b7053SJung-uk Kim     return OBJ_obj2nid(x->sig_alg.algorithm);
307e71b7053SJung-uk Kim }
308*b077aed3SPierre Pronchery 
X509_set0_distinguishing_id(X509 * x,ASN1_OCTET_STRING * d_id)309*b077aed3SPierre Pronchery void X509_set0_distinguishing_id(X509 *x, ASN1_OCTET_STRING *d_id)
310*b077aed3SPierre Pronchery {
311*b077aed3SPierre Pronchery     ASN1_OCTET_STRING_free(x->distinguishing_id);
312*b077aed3SPierre Pronchery     x->distinguishing_id = d_id;
313*b077aed3SPierre Pronchery }
314*b077aed3SPierre Pronchery 
X509_get0_distinguishing_id(X509 * x)315*b077aed3SPierre Pronchery ASN1_OCTET_STRING *X509_get0_distinguishing_id(X509 *x)
316*b077aed3SPierre Pronchery {
317*b077aed3SPierre Pronchery     return x->distinguishing_id;
318*b077aed3SPierre Pronchery }
319