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