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