1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/bn.h> 13e1051a39Sopenharmony_ci#include <openssl/evp.h> 14e1051a39Sopenharmony_ci#include <openssl/asn1.h> 15e1051a39Sopenharmony_ci#include <openssl/asn1t.h> 16e1051a39Sopenharmony_ci#include <openssl/x509.h> 17e1051a39Sopenharmony_ci#include "crypto/x509.h" 18e1051a39Sopenharmony_ci#include <openssl/objects.h> 19e1051a39Sopenharmony_ci#include <openssl/buffer.h> 20e1051a39Sopenharmony_ci#include <openssl/pem.h> 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ciX509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) 23e1051a39Sopenharmony_ci{ 24e1051a39Sopenharmony_ci X509_REQ *ret; 25e1051a39Sopenharmony_ci X509_REQ_INFO *ri; 26e1051a39Sopenharmony_ci int i; 27e1051a39Sopenharmony_ci EVP_PKEY *pktmp; 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ci ret = X509_REQ_new_ex(x->libctx, x->propq); 30e1051a39Sopenharmony_ci if (ret == NULL) { 31e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 32e1051a39Sopenharmony_ci goto err; 33e1051a39Sopenharmony_ci } 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_ci ri = &ret->req_info; 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci ri->version->length = 1; 38e1051a39Sopenharmony_ci ri->version->data = OPENSSL_malloc(1); 39e1051a39Sopenharmony_ci if (ri->version->data == NULL) 40e1051a39Sopenharmony_ci goto err; 41e1051a39Sopenharmony_ci ri->version->data[0] = 0; /* version == 0 */ 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_ci if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x))) 44e1051a39Sopenharmony_ci goto err; 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_ci pktmp = X509_get0_pubkey(x); 47e1051a39Sopenharmony_ci if (pktmp == NULL) 48e1051a39Sopenharmony_ci goto err; 49e1051a39Sopenharmony_ci i = X509_REQ_set_pubkey(ret, pktmp); 50e1051a39Sopenharmony_ci if (!i) 51e1051a39Sopenharmony_ci goto err; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci if (pkey != NULL) { 54e1051a39Sopenharmony_ci if (!X509_REQ_sign(ret, pkey, md)) 55e1051a39Sopenharmony_ci goto err; 56e1051a39Sopenharmony_ci } 57e1051a39Sopenharmony_ci return ret; 58e1051a39Sopenharmony_ci err: 59e1051a39Sopenharmony_ci X509_REQ_free(ret); 60e1051a39Sopenharmony_ci return NULL; 61e1051a39Sopenharmony_ci} 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ciEVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) 64e1051a39Sopenharmony_ci{ 65e1051a39Sopenharmony_ci if (req == NULL) 66e1051a39Sopenharmony_ci return NULL; 67e1051a39Sopenharmony_ci return X509_PUBKEY_get(req->req_info.pubkey); 68e1051a39Sopenharmony_ci} 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ciEVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req) 71e1051a39Sopenharmony_ci{ 72e1051a39Sopenharmony_ci if (req == NULL) 73e1051a39Sopenharmony_ci return NULL; 74e1051a39Sopenharmony_ci return X509_PUBKEY_get0(req->req_info.pubkey); 75e1051a39Sopenharmony_ci} 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ciX509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req) 78e1051a39Sopenharmony_ci{ 79e1051a39Sopenharmony_ci return req->req_info.pubkey; 80e1051a39Sopenharmony_ci} 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ciint X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) 83e1051a39Sopenharmony_ci{ 84e1051a39Sopenharmony_ci EVP_PKEY *xk = NULL; 85e1051a39Sopenharmony_ci int ok = 0; 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci xk = X509_REQ_get_pubkey(x); 88e1051a39Sopenharmony_ci switch (EVP_PKEY_eq(xk, k)) { 89e1051a39Sopenharmony_ci case 1: 90e1051a39Sopenharmony_ci ok = 1; 91e1051a39Sopenharmony_ci break; 92e1051a39Sopenharmony_ci case 0: 93e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH); 94e1051a39Sopenharmony_ci break; 95e1051a39Sopenharmony_ci case -1: 96e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH); 97e1051a39Sopenharmony_ci break; 98e1051a39Sopenharmony_ci case -2: 99e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE); 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci EVP_PKEY_free(xk); 103e1051a39Sopenharmony_ci return ok; 104e1051a39Sopenharmony_ci} 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_ci/* 107e1051a39Sopenharmony_ci * It seems several organisations had the same idea of including a list of 108e1051a39Sopenharmony_ci * extensions in a certificate request. There are at least two OIDs that are 109e1051a39Sopenharmony_ci * used and there may be more: so the list is configurable. 110e1051a39Sopenharmony_ci */ 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_cistatic int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef }; 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_cistatic int *ext_nids = ext_nid_list; 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_ciint X509_REQ_extension_nid(int req_nid) 117e1051a39Sopenharmony_ci{ 118e1051a39Sopenharmony_ci int i, nid; 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci for (i = 0;; i++) { 121e1051a39Sopenharmony_ci nid = ext_nids[i]; 122e1051a39Sopenharmony_ci if (nid == NID_undef) 123e1051a39Sopenharmony_ci return 0; 124e1051a39Sopenharmony_ci else if (req_nid == nid) 125e1051a39Sopenharmony_ci return 1; 126e1051a39Sopenharmony_ci } 127e1051a39Sopenharmony_ci} 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ciint *X509_REQ_get_extension_nids(void) 130e1051a39Sopenharmony_ci{ 131e1051a39Sopenharmony_ci return ext_nids; 132e1051a39Sopenharmony_ci} 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_civoid X509_REQ_set_extension_nids(int *nids) 135e1051a39Sopenharmony_ci{ 136e1051a39Sopenharmony_ci ext_nids = nids; 137e1051a39Sopenharmony_ci} 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ciSTACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) 140e1051a39Sopenharmony_ci{ 141e1051a39Sopenharmony_ci X509_ATTRIBUTE *attr; 142e1051a39Sopenharmony_ci ASN1_TYPE *ext = NULL; 143e1051a39Sopenharmony_ci int idx, *pnid; 144e1051a39Sopenharmony_ci const unsigned char *p; 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ci if (req == NULL || !ext_nids) 147e1051a39Sopenharmony_ci return NULL; 148e1051a39Sopenharmony_ci for (pnid = ext_nids; *pnid != NID_undef; pnid++) { 149e1051a39Sopenharmony_ci idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); 150e1051a39Sopenharmony_ci if (idx == -1) 151e1051a39Sopenharmony_ci continue; 152e1051a39Sopenharmony_ci attr = X509_REQ_get_attr(req, idx); 153e1051a39Sopenharmony_ci ext = X509_ATTRIBUTE_get0_type(attr, 0); 154e1051a39Sopenharmony_ci break; 155e1051a39Sopenharmony_ci } 156e1051a39Sopenharmony_ci if (ext == NULL) /* no extensions is not an error */ 157e1051a39Sopenharmony_ci return sk_X509_EXTENSION_new_null(); 158e1051a39Sopenharmony_ci if (ext->type != V_ASN1_SEQUENCE) 159e1051a39Sopenharmony_ci return NULL; 160e1051a39Sopenharmony_ci p = ext->value.sequence->data; 161e1051a39Sopenharmony_ci return (STACK_OF(X509_EXTENSION) *) 162e1051a39Sopenharmony_ci ASN1_item_d2i(NULL, &p, ext->value.sequence->length, 163e1051a39Sopenharmony_ci ASN1_ITEM_rptr(X509_EXTENSIONS)); 164e1051a39Sopenharmony_ci} 165e1051a39Sopenharmony_ci 166e1051a39Sopenharmony_ci/* 167e1051a39Sopenharmony_ci * Add a STACK_OF extensions to a certificate request: allow alternative OIDs 168e1051a39Sopenharmony_ci * in case we want to create a non standard one. 169e1051a39Sopenharmony_ci */ 170e1051a39Sopenharmony_ciint X509_REQ_add_extensions_nid(X509_REQ *req, 171e1051a39Sopenharmony_ci const STACK_OF(X509_EXTENSION) *exts, int nid) 172e1051a39Sopenharmony_ci{ 173e1051a39Sopenharmony_ci int extlen; 174e1051a39Sopenharmony_ci int rv = 0; 175e1051a39Sopenharmony_ci unsigned char *ext = NULL; 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci /* Generate encoding of extensions */ 178e1051a39Sopenharmony_ci extlen = ASN1_item_i2d((const ASN1_VALUE *)exts, &ext, 179e1051a39Sopenharmony_ci ASN1_ITEM_rptr(X509_EXTENSIONS)); 180e1051a39Sopenharmony_ci if (extlen <= 0) 181e1051a39Sopenharmony_ci return 0; 182e1051a39Sopenharmony_ci rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen); 183e1051a39Sopenharmony_ci OPENSSL_free(ext); 184e1051a39Sopenharmony_ci return rv; 185e1051a39Sopenharmony_ci} 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci/* This is the normal usage: use the "official" OID */ 188e1051a39Sopenharmony_ciint X509_REQ_add_extensions(X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts) 189e1051a39Sopenharmony_ci{ 190e1051a39Sopenharmony_ci return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); 191e1051a39Sopenharmony_ci} 192e1051a39Sopenharmony_ci 193e1051a39Sopenharmony_ci/* Request attribute functions */ 194e1051a39Sopenharmony_ci 195e1051a39Sopenharmony_ciint X509_REQ_get_attr_count(const X509_REQ *req) 196e1051a39Sopenharmony_ci{ 197e1051a39Sopenharmony_ci return X509at_get_attr_count(req->req_info.attributes); 198e1051a39Sopenharmony_ci} 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ciint X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) 201e1051a39Sopenharmony_ci{ 202e1051a39Sopenharmony_ci return X509at_get_attr_by_NID(req->req_info.attributes, nid, lastpos); 203e1051a39Sopenharmony_ci} 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ciint X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, 206e1051a39Sopenharmony_ci int lastpos) 207e1051a39Sopenharmony_ci{ 208e1051a39Sopenharmony_ci return X509at_get_attr_by_OBJ(req->req_info.attributes, obj, lastpos); 209e1051a39Sopenharmony_ci} 210e1051a39Sopenharmony_ci 211e1051a39Sopenharmony_ciX509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) 212e1051a39Sopenharmony_ci{ 213e1051a39Sopenharmony_ci return X509at_get_attr(req->req_info.attributes, loc); 214e1051a39Sopenharmony_ci} 215e1051a39Sopenharmony_ci 216e1051a39Sopenharmony_ciX509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) 217e1051a39Sopenharmony_ci{ 218e1051a39Sopenharmony_ci X509_ATTRIBUTE *attr; 219e1051a39Sopenharmony_ci 220e1051a39Sopenharmony_ci if (req == NULL) { 221e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 222e1051a39Sopenharmony_ci return 0; 223e1051a39Sopenharmony_ci } 224e1051a39Sopenharmony_ci attr = X509at_delete_attr(req->req_info.attributes, loc); 225e1051a39Sopenharmony_ci if (attr != NULL) 226e1051a39Sopenharmony_ci req->req_info.enc.modified = 1; 227e1051a39Sopenharmony_ci return attr; 228e1051a39Sopenharmony_ci} 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ciint X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) 231e1051a39Sopenharmony_ci{ 232e1051a39Sopenharmony_ci if (req == NULL) { 233e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 234e1051a39Sopenharmony_ci return 0; 235e1051a39Sopenharmony_ci } 236e1051a39Sopenharmony_ci if (!X509at_add1_attr(&req->req_info.attributes, attr)) 237e1051a39Sopenharmony_ci return 0; 238e1051a39Sopenharmony_ci req->req_info.enc.modified = 1; 239e1051a39Sopenharmony_ci return 1; 240e1051a39Sopenharmony_ci} 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ciint X509_REQ_add1_attr_by_OBJ(X509_REQ *req, 243e1051a39Sopenharmony_ci const ASN1_OBJECT *obj, int type, 244e1051a39Sopenharmony_ci const unsigned char *bytes, int len) 245e1051a39Sopenharmony_ci{ 246e1051a39Sopenharmony_ci if (req == NULL) { 247e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 248e1051a39Sopenharmony_ci return 0; 249e1051a39Sopenharmony_ci } 250e1051a39Sopenharmony_ci if (!X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj, 251e1051a39Sopenharmony_ci type, bytes, len)) 252e1051a39Sopenharmony_ci return 0; 253e1051a39Sopenharmony_ci req->req_info.enc.modified = 1; 254e1051a39Sopenharmony_ci return 1; 255e1051a39Sopenharmony_ci} 256e1051a39Sopenharmony_ci 257e1051a39Sopenharmony_ciint X509_REQ_add1_attr_by_NID(X509_REQ *req, 258e1051a39Sopenharmony_ci int nid, int type, 259e1051a39Sopenharmony_ci const unsigned char *bytes, int len) 260e1051a39Sopenharmony_ci{ 261e1051a39Sopenharmony_ci if (req == NULL) { 262e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 263e1051a39Sopenharmony_ci return 0; 264e1051a39Sopenharmony_ci } 265e1051a39Sopenharmony_ci if (!X509at_add1_attr_by_NID(&req->req_info.attributes, nid, 266e1051a39Sopenharmony_ci type, bytes, len)) 267e1051a39Sopenharmony_ci return 0; 268e1051a39Sopenharmony_ci req->req_info.enc.modified = 1; 269e1051a39Sopenharmony_ci return 1; 270e1051a39Sopenharmony_ci} 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ciint X509_REQ_add1_attr_by_txt(X509_REQ *req, 273e1051a39Sopenharmony_ci const char *attrname, int type, 274e1051a39Sopenharmony_ci const unsigned char *bytes, int len) 275e1051a39Sopenharmony_ci{ 276e1051a39Sopenharmony_ci if (req == NULL) { 277e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 278e1051a39Sopenharmony_ci return 0; 279e1051a39Sopenharmony_ci } 280e1051a39Sopenharmony_ci if (!X509at_add1_attr_by_txt(&req->req_info.attributes, attrname, 281e1051a39Sopenharmony_ci type, bytes, len)) 282e1051a39Sopenharmony_ci return 0; 283e1051a39Sopenharmony_ci req->req_info.enc.modified = 1; 284e1051a39Sopenharmony_ci return 1; 285e1051a39Sopenharmony_ci} 286e1051a39Sopenharmony_ci 287e1051a39Sopenharmony_cilong X509_REQ_get_version(const X509_REQ *req) 288e1051a39Sopenharmony_ci{ 289e1051a39Sopenharmony_ci return ASN1_INTEGER_get(req->req_info.version); 290e1051a39Sopenharmony_ci} 291e1051a39Sopenharmony_ci 292e1051a39Sopenharmony_ciX509_NAME *X509_REQ_get_subject_name(const X509_REQ *req) 293e1051a39Sopenharmony_ci{ 294e1051a39Sopenharmony_ci return req->req_info.subject; 295e1051a39Sopenharmony_ci} 296e1051a39Sopenharmony_ci 297e1051a39Sopenharmony_civoid X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, 298e1051a39Sopenharmony_ci const X509_ALGOR **palg) 299e1051a39Sopenharmony_ci{ 300e1051a39Sopenharmony_ci if (psig != NULL) 301e1051a39Sopenharmony_ci *psig = req->signature; 302e1051a39Sopenharmony_ci if (palg != NULL) 303e1051a39Sopenharmony_ci *palg = &req->sig_alg; 304e1051a39Sopenharmony_ci} 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_civoid X509_REQ_set0_signature(X509_REQ *req, ASN1_BIT_STRING *psig) 307e1051a39Sopenharmony_ci{ 308e1051a39Sopenharmony_ci if (req->signature) 309e1051a39Sopenharmony_ci ASN1_BIT_STRING_free(req->signature); 310e1051a39Sopenharmony_ci req->signature = psig; 311e1051a39Sopenharmony_ci} 312e1051a39Sopenharmony_ci 313e1051a39Sopenharmony_ciint X509_REQ_set1_signature_algo(X509_REQ *req, X509_ALGOR *palg) 314e1051a39Sopenharmony_ci{ 315e1051a39Sopenharmony_ci return X509_ALGOR_copy(&req->sig_alg, palg); 316e1051a39Sopenharmony_ci} 317e1051a39Sopenharmony_ci 318e1051a39Sopenharmony_ciint X509_REQ_get_signature_nid(const X509_REQ *req) 319e1051a39Sopenharmony_ci{ 320e1051a39Sopenharmony_ci return OBJ_obj2nid(req->sig_alg.algorithm); 321e1051a39Sopenharmony_ci} 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ciint i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) 324e1051a39Sopenharmony_ci{ 325e1051a39Sopenharmony_ci if (req == NULL) { 326e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 327e1051a39Sopenharmony_ci return 0; 328e1051a39Sopenharmony_ci } 329e1051a39Sopenharmony_ci req->req_info.enc.modified = 1; 330e1051a39Sopenharmony_ci return i2d_X509_REQ_INFO(&req->req_info, pp); 331e1051a39Sopenharmony_ci} 332