11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
51cb0ef41Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at
71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html
81cb0ef41Sopenharmony_ci */
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include <stdio.h>
111cb0ef41Sopenharmony_ci#include "internal/cryptlib.h"
121cb0ef41Sopenharmony_ci#include <openssl/bn.h>
131cb0ef41Sopenharmony_ci#include <openssl/evp.h>
141cb0ef41Sopenharmony_ci#include <openssl/asn1.h>
151cb0ef41Sopenharmony_ci#include <openssl/asn1t.h>
161cb0ef41Sopenharmony_ci#include <openssl/x509.h>
171cb0ef41Sopenharmony_ci#include "crypto/x509.h"
181cb0ef41Sopenharmony_ci#include <openssl/objects.h>
191cb0ef41Sopenharmony_ci#include <openssl/buffer.h>
201cb0ef41Sopenharmony_ci#include <openssl/pem.h>
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ciX509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
231cb0ef41Sopenharmony_ci{
241cb0ef41Sopenharmony_ci    X509_REQ *ret;
251cb0ef41Sopenharmony_ci    X509_REQ_INFO *ri;
261cb0ef41Sopenharmony_ci    int i;
271cb0ef41Sopenharmony_ci    EVP_PKEY *pktmp;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci    ret = X509_REQ_new_ex(x->libctx, x->propq);
301cb0ef41Sopenharmony_ci    if (ret == NULL) {
311cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
321cb0ef41Sopenharmony_ci        goto err;
331cb0ef41Sopenharmony_ci    }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci    ri = &ret->req_info;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci    ri->version->length = 1;
381cb0ef41Sopenharmony_ci    ri->version->data = OPENSSL_malloc(1);
391cb0ef41Sopenharmony_ci    if (ri->version->data == NULL)
401cb0ef41Sopenharmony_ci        goto err;
411cb0ef41Sopenharmony_ci    ri->version->data[0] = 0;   /* version == 0 */
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci    if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x)))
441cb0ef41Sopenharmony_ci        goto err;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci    pktmp = X509_get0_pubkey(x);
471cb0ef41Sopenharmony_ci    if (pktmp == NULL)
481cb0ef41Sopenharmony_ci        goto err;
491cb0ef41Sopenharmony_ci    i = X509_REQ_set_pubkey(ret, pktmp);
501cb0ef41Sopenharmony_ci    if (!i)
511cb0ef41Sopenharmony_ci        goto err;
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci    if (pkey != NULL) {
541cb0ef41Sopenharmony_ci        if (!X509_REQ_sign(ret, pkey, md))
551cb0ef41Sopenharmony_ci            goto err;
561cb0ef41Sopenharmony_ci    }
571cb0ef41Sopenharmony_ci    return ret;
581cb0ef41Sopenharmony_ci err:
591cb0ef41Sopenharmony_ci    X509_REQ_free(ret);
601cb0ef41Sopenharmony_ci    return NULL;
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciEVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
641cb0ef41Sopenharmony_ci{
651cb0ef41Sopenharmony_ci    if (req == NULL)
661cb0ef41Sopenharmony_ci        return NULL;
671cb0ef41Sopenharmony_ci    return X509_PUBKEY_get(req->req_info.pubkey);
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciEVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req)
711cb0ef41Sopenharmony_ci{
721cb0ef41Sopenharmony_ci    if (req == NULL)
731cb0ef41Sopenharmony_ci        return NULL;
741cb0ef41Sopenharmony_ci    return X509_PUBKEY_get0(req->req_info.pubkey);
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ciX509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req)
781cb0ef41Sopenharmony_ci{
791cb0ef41Sopenharmony_ci    return req->req_info.pubkey;
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ciint X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
831cb0ef41Sopenharmony_ci{
841cb0ef41Sopenharmony_ci    EVP_PKEY *xk = NULL;
851cb0ef41Sopenharmony_ci    int ok = 0;
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci    xk = X509_REQ_get_pubkey(x);
881cb0ef41Sopenharmony_ci    switch (EVP_PKEY_eq(xk, k)) {
891cb0ef41Sopenharmony_ci    case 1:
901cb0ef41Sopenharmony_ci        ok = 1;
911cb0ef41Sopenharmony_ci        break;
921cb0ef41Sopenharmony_ci    case 0:
931cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH);
941cb0ef41Sopenharmony_ci        break;
951cb0ef41Sopenharmony_ci    case -1:
961cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH);
971cb0ef41Sopenharmony_ci        break;
981cb0ef41Sopenharmony_ci    case -2:
991cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE);
1001cb0ef41Sopenharmony_ci    }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci    EVP_PKEY_free(xk);
1031cb0ef41Sopenharmony_ci    return ok;
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci/*
1071cb0ef41Sopenharmony_ci * It seems several organisations had the same idea of including a list of
1081cb0ef41Sopenharmony_ci * extensions in a certificate request. There are at least two OIDs that are
1091cb0ef41Sopenharmony_ci * used and there may be more: so the list is configurable.
1101cb0ef41Sopenharmony_ci */
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_cistatic int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef };
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_cistatic int *ext_nids = ext_nid_list;
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ciint X509_REQ_extension_nid(int req_nid)
1171cb0ef41Sopenharmony_ci{
1181cb0ef41Sopenharmony_ci    int i, nid;
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci    for (i = 0;; i++) {
1211cb0ef41Sopenharmony_ci        nid = ext_nids[i];
1221cb0ef41Sopenharmony_ci        if (nid == NID_undef)
1231cb0ef41Sopenharmony_ci            return 0;
1241cb0ef41Sopenharmony_ci        else if (req_nid == nid)
1251cb0ef41Sopenharmony_ci            return 1;
1261cb0ef41Sopenharmony_ci    }
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ciint *X509_REQ_get_extension_nids(void)
1301cb0ef41Sopenharmony_ci{
1311cb0ef41Sopenharmony_ci    return ext_nids;
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_civoid X509_REQ_set_extension_nids(int *nids)
1351cb0ef41Sopenharmony_ci{
1361cb0ef41Sopenharmony_ci    ext_nids = nids;
1371cb0ef41Sopenharmony_ci}
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ciSTACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
1401cb0ef41Sopenharmony_ci{
1411cb0ef41Sopenharmony_ci    X509_ATTRIBUTE *attr;
1421cb0ef41Sopenharmony_ci    ASN1_TYPE *ext = NULL;
1431cb0ef41Sopenharmony_ci    int idx, *pnid;
1441cb0ef41Sopenharmony_ci    const unsigned char *p;
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci    if (req == NULL || !ext_nids)
1471cb0ef41Sopenharmony_ci        return NULL;
1481cb0ef41Sopenharmony_ci    for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
1491cb0ef41Sopenharmony_ci        idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
1501cb0ef41Sopenharmony_ci        if (idx == -1)
1511cb0ef41Sopenharmony_ci            continue;
1521cb0ef41Sopenharmony_ci        attr = X509_REQ_get_attr(req, idx);
1531cb0ef41Sopenharmony_ci        ext = X509_ATTRIBUTE_get0_type(attr, 0);
1541cb0ef41Sopenharmony_ci        break;
1551cb0ef41Sopenharmony_ci    }
1561cb0ef41Sopenharmony_ci    if (ext == NULL) /* no extensions is not an error */
1571cb0ef41Sopenharmony_ci        return sk_X509_EXTENSION_new_null();
1581cb0ef41Sopenharmony_ci    if (ext->type != V_ASN1_SEQUENCE)
1591cb0ef41Sopenharmony_ci        return NULL;
1601cb0ef41Sopenharmony_ci    p = ext->value.sequence->data;
1611cb0ef41Sopenharmony_ci    return (STACK_OF(X509_EXTENSION) *)
1621cb0ef41Sopenharmony_ci        ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
1631cb0ef41Sopenharmony_ci                      ASN1_ITEM_rptr(X509_EXTENSIONS));
1641cb0ef41Sopenharmony_ci}
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci/*
1671cb0ef41Sopenharmony_ci * Add a STACK_OF extensions to a certificate request: allow alternative OIDs
1681cb0ef41Sopenharmony_ci * in case we want to create a non standard one.
1691cb0ef41Sopenharmony_ci */
1701cb0ef41Sopenharmony_ciint X509_REQ_add_extensions_nid(X509_REQ *req,
1711cb0ef41Sopenharmony_ci                                const STACK_OF(X509_EXTENSION) *exts, int nid)
1721cb0ef41Sopenharmony_ci{
1731cb0ef41Sopenharmony_ci    int extlen;
1741cb0ef41Sopenharmony_ci    int rv = 0;
1751cb0ef41Sopenharmony_ci    unsigned char *ext = NULL;
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci    /* Generate encoding of extensions */
1781cb0ef41Sopenharmony_ci    extlen = ASN1_item_i2d((const ASN1_VALUE *)exts, &ext,
1791cb0ef41Sopenharmony_ci                           ASN1_ITEM_rptr(X509_EXTENSIONS));
1801cb0ef41Sopenharmony_ci    if (extlen <= 0)
1811cb0ef41Sopenharmony_ci        return 0;
1821cb0ef41Sopenharmony_ci    rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen);
1831cb0ef41Sopenharmony_ci    OPENSSL_free(ext);
1841cb0ef41Sopenharmony_ci    return rv;
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci/* This is the normal usage: use the "official" OID */
1881cb0ef41Sopenharmony_ciint X509_REQ_add_extensions(X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts)
1891cb0ef41Sopenharmony_ci{
1901cb0ef41Sopenharmony_ci    return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
1911cb0ef41Sopenharmony_ci}
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci/* Request attribute functions */
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ciint X509_REQ_get_attr_count(const X509_REQ *req)
1961cb0ef41Sopenharmony_ci{
1971cb0ef41Sopenharmony_ci    return X509at_get_attr_count(req->req_info.attributes);
1981cb0ef41Sopenharmony_ci}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ciint X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos)
2011cb0ef41Sopenharmony_ci{
2021cb0ef41Sopenharmony_ci    return X509at_get_attr_by_NID(req->req_info.attributes, nid, lastpos);
2031cb0ef41Sopenharmony_ci}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ciint X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj,
2061cb0ef41Sopenharmony_ci                             int lastpos)
2071cb0ef41Sopenharmony_ci{
2081cb0ef41Sopenharmony_ci    return X509at_get_attr_by_OBJ(req->req_info.attributes, obj, lastpos);
2091cb0ef41Sopenharmony_ci}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ciX509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
2121cb0ef41Sopenharmony_ci{
2131cb0ef41Sopenharmony_ci    return X509at_get_attr(req->req_info.attributes, loc);
2141cb0ef41Sopenharmony_ci}
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ciX509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
2171cb0ef41Sopenharmony_ci{
2181cb0ef41Sopenharmony_ci    X509_ATTRIBUTE *attr;
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci    if (req == NULL) {
2211cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
2221cb0ef41Sopenharmony_ci        return NULL;
2231cb0ef41Sopenharmony_ci    }
2241cb0ef41Sopenharmony_ci    attr = X509at_delete_attr(req->req_info.attributes, loc);
2251cb0ef41Sopenharmony_ci    if (attr != NULL)
2261cb0ef41Sopenharmony_ci        req->req_info.enc.modified = 1;
2271cb0ef41Sopenharmony_ci    return attr;
2281cb0ef41Sopenharmony_ci}
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ciint X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
2311cb0ef41Sopenharmony_ci{
2321cb0ef41Sopenharmony_ci    if (req == NULL) {
2331cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
2341cb0ef41Sopenharmony_ci        return 0;
2351cb0ef41Sopenharmony_ci    }
2361cb0ef41Sopenharmony_ci    if (!X509at_add1_attr(&req->req_info.attributes, attr))
2371cb0ef41Sopenharmony_ci        return 0;
2381cb0ef41Sopenharmony_ci    req->req_info.enc.modified = 1;
2391cb0ef41Sopenharmony_ci    return 1;
2401cb0ef41Sopenharmony_ci}
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ciint X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
2431cb0ef41Sopenharmony_ci                              const ASN1_OBJECT *obj, int type,
2441cb0ef41Sopenharmony_ci                              const unsigned char *bytes, int len)
2451cb0ef41Sopenharmony_ci{
2461cb0ef41Sopenharmony_ci    if (req == NULL) {
2471cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
2481cb0ef41Sopenharmony_ci        return 0;
2491cb0ef41Sopenharmony_ci    }
2501cb0ef41Sopenharmony_ci    if (!X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj,
2511cb0ef41Sopenharmony_ci                                 type, bytes, len))
2521cb0ef41Sopenharmony_ci        return 0;
2531cb0ef41Sopenharmony_ci    req->req_info.enc.modified = 1;
2541cb0ef41Sopenharmony_ci    return 1;
2551cb0ef41Sopenharmony_ci}
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ciint X509_REQ_add1_attr_by_NID(X509_REQ *req,
2581cb0ef41Sopenharmony_ci                              int nid, int type,
2591cb0ef41Sopenharmony_ci                              const unsigned char *bytes, int len)
2601cb0ef41Sopenharmony_ci{
2611cb0ef41Sopenharmony_ci    if (req == NULL) {
2621cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
2631cb0ef41Sopenharmony_ci        return 0;
2641cb0ef41Sopenharmony_ci    }
2651cb0ef41Sopenharmony_ci    if (!X509at_add1_attr_by_NID(&req->req_info.attributes, nid,
2661cb0ef41Sopenharmony_ci                                 type, bytes, len))
2671cb0ef41Sopenharmony_ci        return 0;
2681cb0ef41Sopenharmony_ci    req->req_info.enc.modified = 1;
2691cb0ef41Sopenharmony_ci    return 1;
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ciint X509_REQ_add1_attr_by_txt(X509_REQ *req,
2731cb0ef41Sopenharmony_ci                              const char *attrname, int type,
2741cb0ef41Sopenharmony_ci                              const unsigned char *bytes, int len)
2751cb0ef41Sopenharmony_ci{
2761cb0ef41Sopenharmony_ci    if (req == NULL) {
2771cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
2781cb0ef41Sopenharmony_ci        return 0;
2791cb0ef41Sopenharmony_ci    }
2801cb0ef41Sopenharmony_ci    if (!X509at_add1_attr_by_txt(&req->req_info.attributes, attrname,
2811cb0ef41Sopenharmony_ci                                 type, bytes, len))
2821cb0ef41Sopenharmony_ci        return 0;
2831cb0ef41Sopenharmony_ci    req->req_info.enc.modified = 1;
2841cb0ef41Sopenharmony_ci    return 1;
2851cb0ef41Sopenharmony_ci}
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_cilong X509_REQ_get_version(const X509_REQ *req)
2881cb0ef41Sopenharmony_ci{
2891cb0ef41Sopenharmony_ci    return ASN1_INTEGER_get(req->req_info.version);
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ciX509_NAME *X509_REQ_get_subject_name(const X509_REQ *req)
2931cb0ef41Sopenharmony_ci{
2941cb0ef41Sopenharmony_ci    return req->req_info.subject;
2951cb0ef41Sopenharmony_ci}
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_civoid X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
2981cb0ef41Sopenharmony_ci                             const X509_ALGOR **palg)
2991cb0ef41Sopenharmony_ci{
3001cb0ef41Sopenharmony_ci    if (psig != NULL)
3011cb0ef41Sopenharmony_ci        *psig = req->signature;
3021cb0ef41Sopenharmony_ci    if (palg != NULL)
3031cb0ef41Sopenharmony_ci        *palg = &req->sig_alg;
3041cb0ef41Sopenharmony_ci}
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_civoid X509_REQ_set0_signature(X509_REQ *req, ASN1_BIT_STRING *psig)
3071cb0ef41Sopenharmony_ci{
3081cb0ef41Sopenharmony_ci    if (req->signature)
3091cb0ef41Sopenharmony_ci        ASN1_BIT_STRING_free(req->signature);
3101cb0ef41Sopenharmony_ci    req->signature = psig;
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ciint X509_REQ_set1_signature_algo(X509_REQ *req, X509_ALGOR *palg)
3141cb0ef41Sopenharmony_ci{
3151cb0ef41Sopenharmony_ci    return X509_ALGOR_copy(&req->sig_alg, palg);
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ciint X509_REQ_get_signature_nid(const X509_REQ *req)
3191cb0ef41Sopenharmony_ci{
3201cb0ef41Sopenharmony_ci    return OBJ_obj2nid(req->sig_alg.algorithm);
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ciint i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp)
3241cb0ef41Sopenharmony_ci{
3251cb0ef41Sopenharmony_ci    if (req == NULL) {
3261cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
3271cb0ef41Sopenharmony_ci        return 0;
3281cb0ef41Sopenharmony_ci    }
3291cb0ef41Sopenharmony_ci    req->req_info.enc.modified = 1;
3301cb0ef41Sopenharmony_ci    return i2d_X509_REQ_INFO(&req->req_info, pp);
3311cb0ef41Sopenharmony_ci}
332