| /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 
 |  * All rights reserved. | 
 |  * | 
 |  * This package is an SSL implementation written | 
 |  * by Eric Young (eay@cryptsoft.com). | 
 |  * The implementation was written so as to conform with Netscapes SSL. | 
 |  * | 
 |  * This library is free for commercial and non-commercial use as long as | 
 |  * the following conditions are aheared to.  The following conditions | 
 |  * apply to all code found in this distribution, be it the RC4, RSA, | 
 |  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation | 
 |  * included with this distribution is covered by the same copyright terms | 
 |  * except that the holder is Tim Hudson (tjh@cryptsoft.com). | 
 |  * | 
 |  * Copyright remains Eric Young's, and as such any Copyright notices in | 
 |  * the code are not to be removed. | 
 |  * If this package is used in a product, Eric Young should be given attribution | 
 |  * as the author of the parts of the library used. | 
 |  * This can be in the form of a textual message at program startup or | 
 |  * in documentation (online or textual) provided with the package. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * 1. Redistributions of source code must retain the copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * 3. All advertising materials mentioning features or use of this software | 
 |  *    must display the following acknowledgement: | 
 |  *    "This product includes cryptographic software written by | 
 |  *     Eric Young (eay@cryptsoft.com)" | 
 |  *    The word 'cryptographic' can be left out if the rouines from the library | 
 |  *    being used are not cryptographic related :-). | 
 |  * 4. If you include any Windows specific code (or a derivative thereof) from | 
 |  *    the apps directory (application code) you must include an acknowledgement: | 
 |  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | 
 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 
 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
 |  * SUCH DAMAGE. | 
 |  * | 
 |  * The licence and distribution terms for any publically available version or | 
 |  * derivative of this code cannot be changed.  i.e. this code cannot simply be | 
 |  * copied and put under another distribution licence | 
 |  * [including the GNU Public Licence.] */ | 
 |  | 
 | #include <assert.h> | 
 | #include <limits.h> | 
 | #include <stdio.h> | 
 |  | 
 | #include <openssl/asn1t.h> | 
 | #include <openssl/evp.h> | 
 | #include <openssl/mem.h> | 
 | #include <openssl/obj.h> | 
 | #include <openssl/pool.h> | 
 | #include <openssl/thread.h> | 
 | #include <openssl/x509.h> | 
 |  | 
 | #include "../asn1/internal.h" | 
 | #include "../bytestring/internal.h" | 
 | #include "../internal.h" | 
 | #include "internal.h" | 
 |  | 
 | static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | 
 |  | 
 | ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = { | 
 |     ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), | 
 |     ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER), | 
 |     ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR), | 
 |     ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), | 
 |     ASN1_SIMPLE(X509_CINF, validity, X509_VAL), | 
 |     ASN1_SIMPLE(X509_CINF, subject, X509_NAME), | 
 |     ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), | 
 |     ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), | 
 |     ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), | 
 |     ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3), | 
 | } ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF) | 
 |  | 
 | IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) | 
 |  | 
 | // x509_new_null returns a new |X509| object where the |cert_info|, |sig_alg|, | 
 | // and |signature| fields are not yet filled in. | 
 | static X509 *x509_new_null(void) { | 
 |   X509 *ret = reinterpret_cast<X509 *>(OPENSSL_zalloc(sizeof(X509))); | 
 |   if (ret == NULL) { | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   ret->references = 1; | 
 |   ret->ex_pathlen = -1; | 
 |   CRYPTO_new_ex_data(&ret->ex_data); | 
 |   CRYPTO_MUTEX_init(&ret->lock); | 
 |   return ret; | 
 | } | 
 |  | 
 | X509 *X509_new(void) { | 
 |   X509 *ret = x509_new_null(); | 
 |   if (ret == NULL) { | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   ret->cert_info = X509_CINF_new(); | 
 |   ret->sig_alg = X509_ALGOR_new(); | 
 |   ret->signature = ASN1_BIT_STRING_new(); | 
 |   if (ret->cert_info == NULL || ret->sig_alg == NULL || | 
 |       ret->signature == NULL) { | 
 |     X509_free(ret); | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | void X509_free(X509 *x509) { | 
 |   if (x509 == NULL || !CRYPTO_refcount_dec_and_test_zero(&x509->references)) { | 
 |     return; | 
 |   } | 
 |  | 
 |   CRYPTO_free_ex_data(&g_ex_data_class, x509, &x509->ex_data); | 
 |  | 
 |   X509_CINF_free(x509->cert_info); | 
 |   X509_ALGOR_free(x509->sig_alg); | 
 |   ASN1_BIT_STRING_free(x509->signature); | 
 |   ASN1_OCTET_STRING_free(x509->skid); | 
 |   AUTHORITY_KEYID_free(x509->akid); | 
 |   CRL_DIST_POINTS_free(x509->crldp); | 
 |   GENERAL_NAMES_free(x509->altname); | 
 |   NAME_CONSTRAINTS_free(x509->nc); | 
 |   X509_CERT_AUX_free(x509->aux); | 
 |   CRYPTO_MUTEX_cleanup(&x509->lock); | 
 |  | 
 |   OPENSSL_free(x509); | 
 | } | 
 |  | 
 | static X509 *x509_parse(CBS *cbs, CRYPTO_BUFFER *buf) { | 
 |   CBS cert, tbs, sigalg, sig; | 
 |   if (!CBS_get_asn1(cbs, &cert, CBS_ASN1_SEQUENCE) || | 
 |       // Bound the length to comfortably fit in an int. Lengths in this | 
 |       // module often omit overflow checks. | 
 |       CBS_len(&cert) > INT_MAX / 2 || | 
 |       !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE) || | 
 |       !CBS_get_asn1_element(&cert, &sigalg, CBS_ASN1_SEQUENCE)) { | 
 |     OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   // For just the signature field, we accept non-minimal BER lengths, though not | 
 |   // indefinite-length encoding. See b/18228011. | 
 |   // | 
 |   // TODO(crbug.com/boringssl/354): Switch the affected callers to convert the | 
 |   // certificate before parsing and then remove this workaround. | 
 |   CBS_ASN1_TAG tag; | 
 |   size_t header_len; | 
 |   int indefinite; | 
 |   if (!CBS_get_any_ber_asn1_element(&cert, &sig, &tag, &header_len, | 
 |                                     /*out_ber_found=*/NULL, | 
 |                                     &indefinite) || | 
 |       tag != CBS_ASN1_BITSTRING || indefinite ||  // | 
 |       !CBS_skip(&sig, header_len) ||              // | 
 |       CBS_len(&cert) != 0) { | 
 |     OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   X509 *ret = x509_new_null(); | 
 |   if (ret == NULL) { | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   { | 
 |     // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled | 
 |     // from the tasn_*.c implementation, replace this with |CBS|-based | 
 |     // functions. | 
 |     const uint8_t *inp = CBS_data(&tbs); | 
 |     if (ASN1_item_ex_d2i((ASN1_VALUE **)&ret->cert_info, &inp, CBS_len(&tbs), | 
 |                          ASN1_ITEM_rptr(X509_CINF), /*tag=*/-1, | 
 |                          /*aclass=*/0, /*opt=*/0, buf) <= 0 || | 
 |         inp != CBS_data(&tbs) + CBS_len(&tbs)) { | 
 |       goto err; | 
 |     } | 
 |  | 
 |     inp = CBS_data(&sigalg); | 
 |     ret->sig_alg = d2i_X509_ALGOR(NULL, &inp, CBS_len(&sigalg)); | 
 |     if (ret->sig_alg == NULL || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) { | 
 |       goto err; | 
 |     } | 
 |  | 
 |     inp = CBS_data(&sig); | 
 |     ret->signature = c2i_ASN1_BIT_STRING(NULL, &inp, CBS_len(&sig)); | 
 |     if (ret->signature == NULL || inp != CBS_data(&sig) + CBS_len(&sig)) { | 
 |       goto err; | 
 |     } | 
 |  | 
 |     // The version must be one of v1(0), v2(1), or v3(2). | 
 |     long version = X509_VERSION_1; | 
 |     if (ret->cert_info->version != NULL) { | 
 |       version = ASN1_INTEGER_get(ret->cert_info->version); | 
 |       // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should | 
 |       // also be rejected here. This means an explicitly-encoded X.509v1 | 
 |       // version. v1 is DEFAULT, so DER requires it be omitted. | 
 |       if (version < X509_VERSION_1 || version > X509_VERSION_3) { | 
 |         OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); | 
 |         goto err; | 
 |       } | 
 |     } | 
 |  | 
 |     // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3. | 
 |     if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL || | 
 |                                       ret->cert_info->subjectUID != NULL)) { | 
 |       OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); | 
 |       goto err; | 
 |     } | 
 |  | 
 |     // Per RFC 5280, section 4.1.2.9, extensions require v3. | 
 |     if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) { | 
 |       OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); | 
 |       goto err; | 
 |     } | 
 |  | 
 |     return ret; | 
 |   } | 
 |  | 
 | err: | 
 |   X509_free(ret); | 
 |   return NULL; | 
 | } | 
 |  | 
 | X509 *d2i_X509(X509 **out, const uint8_t **inp, long len) { | 
 |   X509 *ret = NULL; | 
 |   if (len < 0) { | 
 |     OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); | 
 |     goto err; | 
 |   } | 
 |  | 
 |   CBS cbs; | 
 |   CBS_init(&cbs, *inp, (size_t)len); | 
 |   ret = x509_parse(&cbs, NULL); | 
 |   if (ret == NULL) { | 
 |     goto err; | 
 |   } | 
 |  | 
 |   *inp = CBS_data(&cbs); | 
 |  | 
 | err: | 
 |   if (out != NULL) { | 
 |     X509_free(*out); | 
 |     *out = ret; | 
 |   } | 
 |   return ret; | 
 | } | 
 |  | 
 | int i2d_X509(X509 *x509, uint8_t **outp) { | 
 |   if (x509 == NULL) { | 
 |     OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); | 
 |     return -1; | 
 |   } | 
 |  | 
 |   CBB cbb, cert; | 
 |   int len; | 
 |   if (!CBB_init(&cbb, 64) ||  // | 
 |       !CBB_add_asn1(&cbb, &cert, CBS_ASN1_SEQUENCE)) { | 
 |     goto err; | 
 |   } | 
 |  | 
 |   // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled | 
 |   // from the tasn_*.c implementation, replace this with |CBS|-based functions. | 
 |   uint8_t *out; | 
 |   len = i2d_X509_CINF(x509->cert_info, NULL); | 
 |   if (len < 0 ||  // | 
 |       !CBB_add_space(&cert, &out, (size_t)len) || | 
 |       i2d_X509_CINF(x509->cert_info, &out) != len) { | 
 |     goto err; | 
 |   } | 
 |  | 
 |   len = i2d_X509_ALGOR(x509->sig_alg, NULL); | 
 |   if (len < 0 ||  // | 
 |       !CBB_add_space(&cert, &out, (size_t)len) || | 
 |       i2d_X509_ALGOR(x509->sig_alg, &out) != len) { | 
 |     goto err; | 
 |   } | 
 |  | 
 |   len = i2d_ASN1_BIT_STRING(x509->signature, NULL); | 
 |   if (len < 0 ||  // | 
 |       !CBB_add_space(&cert, &out, (size_t)len) || | 
 |       i2d_ASN1_BIT_STRING(x509->signature, &out) != len) { | 
 |     goto err; | 
 |   } | 
 |  | 
 |   return CBB_finish_i2d(&cbb, outp); | 
 |  | 
 | err: | 
 |   CBB_cleanup(&cbb); | 
 |   return -1; | 
 | } | 
 |  | 
 | static int x509_new_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { | 
 |   *pval = (ASN1_VALUE *)X509_new(); | 
 |   return *pval != NULL; | 
 | } | 
 |  | 
 | static void x509_free_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { | 
 |   X509_free((X509 *)*pval); | 
 |   *pval = NULL; | 
 | } | 
 |  | 
 | static int x509_d2i_cb(ASN1_VALUE **pval, const unsigned char **in, long len, | 
 |                        const ASN1_ITEM *it, int opt, ASN1_TLC *ctx) { | 
 |   if (len < 0) { | 
 |     OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); | 
 |     return 0; | 
 |   } | 
 |  | 
 |   CBS cbs; | 
 |   CBS_init(&cbs, *in, len); | 
 |   if (opt && !CBS_peek_asn1_tag(&cbs, CBS_ASN1_SEQUENCE)) { | 
 |     return -1; | 
 |   } | 
 |  | 
 |   X509 *ret = x509_parse(&cbs, NULL); | 
 |   if (ret == NULL) { | 
 |     return 0; | 
 |   } | 
 |  | 
 |   *in = CBS_data(&cbs); | 
 |   X509_free((X509 *)*pval); | 
 |   *pval = (ASN1_VALUE *)ret; | 
 |   return 1; | 
 | } | 
 |  | 
 | static int x509_i2d_cb(ASN1_VALUE **pval, unsigned char **out, | 
 |                        const ASN1_ITEM *it) { | 
 |   return i2d_X509((X509 *)*pval, out); | 
 | } | 
 |  | 
 | static const ASN1_EXTERN_FUNCS x509_extern_funcs = { | 
 |     x509_new_cb, | 
 |     x509_free_cb, | 
 |     x509_d2i_cb, | 
 |     x509_i2d_cb, | 
 | }; | 
 |  | 
 | IMPLEMENT_EXTERN_ASN1(X509, V_ASN1_SEQUENCE, x509_extern_funcs) | 
 |  | 
 | X509 *X509_dup(X509 *x509) { | 
 |   uint8_t *der = NULL; | 
 |   int len = i2d_X509(x509, &der); | 
 |   if (len < 0) { | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   const uint8_t *inp = der; | 
 |   X509 *ret = d2i_X509(NULL, &inp, len); | 
 |   OPENSSL_free(der); | 
 |   return ret; | 
 | } | 
 |  | 
 | X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) { | 
 |   CBS cbs; | 
 |   CBS_init(&cbs, CRYPTO_BUFFER_data(buf), CRYPTO_BUFFER_len(buf)); | 
 |   X509 *ret = x509_parse(&cbs, buf); | 
 |   if (ret == NULL || CBS_len(&cbs) != 0) { | 
 |     X509_free(ret); | 
 |     return NULL; | 
 |   } | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | int X509_up_ref(X509 *x) { | 
 |   CRYPTO_refcount_inc(&x->references); | 
 |   return 1; | 
 | } | 
 |  | 
 | int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, | 
 |                           CRYPTO_EX_dup *dup_unused, | 
 |                           CRYPTO_EX_free *free_func) { | 
 |   return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func); | 
 | } | 
 |  | 
 | int X509_set_ex_data(X509 *r, int idx, void *arg) { | 
 |   return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); | 
 | } | 
 |  | 
 | void *X509_get_ex_data(X509 *r, int idx) { | 
 |   return (CRYPTO_get_ex_data(&r->ex_data, idx)); | 
 | } | 
 |  | 
 | // X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with | 
 | // extra info tagged on the end. Since these functions set how a certificate | 
 | // is trusted they should only be used when the certificate comes from a | 
 | // reliable source such as local storage. | 
 |  | 
 | X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) { | 
 |   const unsigned char *q = *pp; | 
 |   X509 *ret; | 
 |   int freeret = 0; | 
 |  | 
 |   if (!a || *a == NULL) { | 
 |     freeret = 1; | 
 |   } | 
 |   ret = d2i_X509(a, &q, length); | 
 |   // If certificate unreadable then forget it | 
 |   if (!ret) { | 
 |     return NULL; | 
 |   } | 
 |   // update length | 
 |   length -= q - *pp; | 
 |   // Parse auxiliary information if there is any. | 
 |   if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) { | 
 |     goto err; | 
 |   } | 
 |   *pp = q; | 
 |   return ret; | 
 | err: | 
 |   if (freeret) { | 
 |     X509_free(ret); | 
 |     if (a) { | 
 |       *a = NULL; | 
 |     } | 
 |   } | 
 |   return NULL; | 
 | } | 
 |  | 
 | // Serialize trusted certificate to *pp or just return the required buffer | 
 | // length if pp == NULL.  We ultimately want to avoid modifying *pp in the | 
 | // error path, but that depends on similar hygiene in lower-level functions. | 
 | // Here we avoid compounding the problem. | 
 | static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) { | 
 |   int length, tmplen; | 
 |   unsigned char *start = pp != NULL ? *pp : NULL; | 
 |  | 
 |   assert(pp == NULL || *pp != NULL); | 
 |  | 
 |   // This might perturb *pp on error, but fixing that belongs in i2d_X509() | 
 |   // not here.  It should be that if a == NULL length is zero, but we check | 
 |   // both just in case. | 
 |   length = i2d_X509(a, pp); | 
 |   if (length <= 0 || a == NULL) { | 
 |     return length; | 
 |   } | 
 |  | 
 |   if (a->aux != NULL) { | 
 |     tmplen = i2d_X509_CERT_AUX(a->aux, pp); | 
 |     if (tmplen < 0) { | 
 |       if (start != NULL) { | 
 |         *pp = start; | 
 |       } | 
 |       return tmplen; | 
 |     } | 
 |     length += tmplen; | 
 |   } | 
 |  | 
 |   return length; | 
 | } | 
 |  | 
 | // Serialize trusted certificate to *pp, or just return the required buffer | 
 | // length if pp == NULL. | 
 | // | 
 | // When pp is not NULL, but *pp == NULL, we allocate the buffer, but since | 
 | // we're writing two ASN.1 objects back to back, we can't have i2d_X509() do | 
 | // the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the | 
 | // allocated buffer. | 
 | int i2d_X509_AUX(X509 *a, unsigned char **pp) { | 
 |   int length; | 
 |   unsigned char *tmp; | 
 |  | 
 |   // Buffer provided by caller | 
 |   if (pp == NULL || *pp != NULL) { | 
 |     return i2d_x509_aux_internal(a, pp); | 
 |   } | 
 |  | 
 |   // Obtain the combined length | 
 |   if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) { | 
 |     return length; | 
 |   } | 
 |  | 
 |   // Allocate requisite combined storage | 
 |   *pp = tmp = reinterpret_cast<uint8_t *>(OPENSSL_malloc(length)); | 
 |   if (tmp == NULL) { | 
 |     return -1;  // Push error onto error stack? | 
 |   } | 
 |  | 
 |   // Encode, but keep *pp at the originally malloced pointer | 
 |   length = i2d_x509_aux_internal(a, &tmp); | 
 |   if (length <= 0) { | 
 |     OPENSSL_free(*pp); | 
 |     *pp = NULL; | 
 |   } | 
 |   return length; | 
 | } | 
 |  | 
 | int i2d_re_X509_tbs(X509 *x509, unsigned char **outp) { | 
 |   asn1_encoding_clear(&x509->cert_info->enc); | 
 |   return i2d_X509_CINF(x509->cert_info, outp); | 
 | } | 
 |  | 
 | int i2d_X509_tbs(X509 *x509, unsigned char **outp) { | 
 |   return i2d_X509_CINF(x509->cert_info, outp); | 
 | } | 
 |  | 
 | int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) { | 
 |   X509_ALGOR *copy1 = X509_ALGOR_dup(algo); | 
 |   X509_ALGOR *copy2 = X509_ALGOR_dup(algo); | 
 |   if (copy1 == NULL || copy2 == NULL) { | 
 |     X509_ALGOR_free(copy1); | 
 |     X509_ALGOR_free(copy2); | 
 |     return 0; | 
 |   } | 
 |  | 
 |   X509_ALGOR_free(x509->sig_alg); | 
 |   x509->sig_alg = copy1; | 
 |   X509_ALGOR_free(x509->cert_info->signature); | 
 |   x509->cert_info->signature = copy2; | 
 |   return 1; | 
 | } | 
 |  | 
 | int X509_set1_signature_value(X509 *x509, const uint8_t *sig, size_t sig_len) { | 
 |   if (!ASN1_STRING_set(x509->signature, sig, sig_len)) { | 
 |     return 0; | 
 |   } | 
 |   x509->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); | 
 |   x509->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; | 
 |   return 1; | 
 | } | 
 |  | 
 | void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, | 
 |                          const X509 *x) { | 
 |   if (psig) { | 
 |     *psig = x->signature; | 
 |   } | 
 |   if (palg) { | 
 |     *palg = x->sig_alg; | 
 |   } | 
 | } | 
 |  | 
 | int X509_get_signature_nid(const X509 *x) { | 
 |   return OBJ_obj2nid(x->sig_alg->algorithm); | 
 | } |