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