1 /* $OpenBSD: x509_req.c,v 1.43 2024/08/31 10:16:52 tb Exp $ */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <stdio.h> 60 61 #include <openssl/opensslconf.h> 62 63 #include <openssl/asn1.h> 64 #include <openssl/asn1t.h> 65 #include <openssl/bn.h> 66 #include <openssl/buffer.h> 67 #include <openssl/err.h> 68 #include <openssl/evp.h> 69 #include <openssl/objects.h> 70 #include <openssl/pem.h> 71 #include <openssl/x509.h> 72 73 #include "asn1_local.h" 74 #include "evp_local.h" 75 #include "x509_local.h" 76 77 X509_REQ * 78 X509_to_X509_REQ(X509 *x509, EVP_PKEY *signing_key, const EVP_MD *signing_md) 79 { 80 X509_REQ *req; 81 X509_NAME *subject; 82 EVP_PKEY *public_key; 83 84 if ((req = X509_REQ_new()) == NULL) { 85 X509error(ERR_R_MALLOC_FAILURE); 86 goto err; 87 } 88 89 if ((subject = X509_get_subject_name(x509)) == NULL) 90 goto err; 91 if (!X509_REQ_set_subject_name(req, subject)) 92 goto err; 93 94 if ((public_key = X509_get0_pubkey(x509)) == NULL) 95 goto err; 96 if (!X509_REQ_set_pubkey(req, public_key)) 97 goto err; 98 99 if (signing_key != NULL) { 100 if (!X509_REQ_sign(req, signing_key, signing_md)) 101 goto err; 102 } 103 104 return req; 105 106 err: 107 X509_REQ_free(req); 108 109 return NULL; 110 } 111 LCRYPTO_ALIAS(X509_to_X509_REQ); 112 113 EVP_PKEY * 114 X509_REQ_get_pubkey(X509_REQ *req) 115 { 116 if (req == NULL || req->req_info == NULL) 117 return NULL; 118 return X509_PUBKEY_get(req->req_info->pubkey); 119 } 120 LCRYPTO_ALIAS(X509_REQ_get_pubkey); 121 122 EVP_PKEY * 123 X509_REQ_get0_pubkey(X509_REQ *req) 124 { 125 if (req == NULL || req->req_info == NULL) 126 return NULL; 127 return X509_PUBKEY_get0(req->req_info->pubkey); 128 } 129 LCRYPTO_ALIAS(X509_REQ_get0_pubkey); 130 131 int 132 X509_REQ_check_private_key(X509_REQ *req, EVP_PKEY *pkey) 133 { 134 EVP_PKEY *req_pubkey = NULL; 135 int ret; 136 137 if ((req_pubkey = X509_REQ_get0_pubkey(req)) == NULL) 138 return 0; 139 140 if ((ret = EVP_PKEY_cmp(req_pubkey, pkey)) == 1) 141 return 1; 142 143 switch (ret) { 144 case 0: 145 X509error(X509_R_KEY_VALUES_MISMATCH); 146 return 0; 147 case -1: 148 X509error(X509_R_KEY_TYPE_MISMATCH); 149 return 0; 150 case -2: 151 #ifndef OPENSSL_NO_EC 152 if (pkey->type == EVP_PKEY_EC) { 153 X509error(ERR_R_EC_LIB); 154 return 0; 155 } 156 #endif 157 #ifndef OPENSSL_NO_DH 158 if (pkey->type == EVP_PKEY_DH) { 159 /* No idea */ 160 X509error(X509_R_CANT_CHECK_DH_KEY); 161 return 0; 162 } 163 #endif 164 X509error(X509_R_UNKNOWN_KEY_TYPE); 165 return 0; 166 } 167 168 return 0; 169 } 170 LCRYPTO_ALIAS(X509_REQ_check_private_key); 171 172 int 173 X509_REQ_extension_nid(int nid) 174 { 175 return nid == NID_ext_req || nid == NID_ms_ext_req; 176 } 177 LCRYPTO_ALIAS(X509_REQ_extension_nid); 178 179 STACK_OF(X509_EXTENSION) * 180 X509_REQ_get_extensions(X509_REQ *req) 181 { 182 X509_ATTRIBUTE *attr; 183 ASN1_TYPE *ext = NULL; 184 int idx; 185 186 if (req == NULL || req->req_info == NULL) 187 return NULL; 188 189 if ((idx = X509_REQ_get_attr_by_NID(req, NID_ext_req, -1)) == -1) 190 idx = X509_REQ_get_attr_by_NID(req, NID_ms_ext_req, -1); 191 if (idx == -1) 192 return NULL; 193 194 if ((attr = X509_REQ_get_attr(req, idx)) == NULL) 195 return NULL; 196 if ((ext = X509_ATTRIBUTE_get0_type(attr, 0)) == NULL) 197 return NULL; 198 199 return ASN1_TYPE_unpack_sequence(&X509_EXTENSIONS_it, ext); 200 } 201 LCRYPTO_ALIAS(X509_REQ_get_extensions); 202 203 /* 204 * Add a STACK_OF extensions to a certificate request: allow alternative OIDs 205 * in case we want to create a non-standard one. 206 */ 207 208 int 209 X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, 210 int nid) 211 { 212 unsigned char *ext = NULL; 213 int extlen; 214 int ret; 215 216 if ((extlen = i2d_X509_EXTENSIONS(exts, &ext)) <= 0) 217 return 0; 218 219 ret = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen); 220 free(ext); 221 222 return ret; 223 } 224 LCRYPTO_ALIAS(X509_REQ_add_extensions_nid); 225 226 /* This is the normal usage: use the "official" OID */ 227 int 228 X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) 229 { 230 return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); 231 } 232 LCRYPTO_ALIAS(X509_REQ_add_extensions); 233 234 /* Request attribute functions */ 235 236 int 237 X509_REQ_get_attr_count(const X509_REQ *req) 238 { 239 return sk_X509_ATTRIBUTE_num(req->req_info->attributes); 240 } 241 LCRYPTO_ALIAS(X509_REQ_get_attr_count); 242 243 int 244 X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) 245 { 246 return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); 247 } 248 LCRYPTO_ALIAS(X509_REQ_get_attr_by_NID); 249 250 int 251 X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, 252 int lastpos) 253 { 254 return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); 255 } 256 LCRYPTO_ALIAS(X509_REQ_get_attr_by_OBJ); 257 258 X509_ATTRIBUTE * 259 X509_REQ_get_attr(const X509_REQ *req, int loc) 260 { 261 return sk_X509_ATTRIBUTE_value(req->req_info->attributes, loc); 262 } 263 LCRYPTO_ALIAS(X509_REQ_get_attr); 264 265 X509_ATTRIBUTE * 266 X509_REQ_delete_attr(X509_REQ *req, int loc) 267 { 268 return sk_X509_ATTRIBUTE_delete(req->req_info->attributes, loc); 269 } 270 LCRYPTO_ALIAS(X509_REQ_delete_attr); 271 272 int 273 X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) 274 { 275 if (X509at_add1_attr(&req->req_info->attributes, attr)) 276 return 1; 277 return 0; 278 } 279 LCRYPTO_ALIAS(X509_REQ_add1_attr); 280 281 int 282 X509_REQ_add1_attr_by_OBJ(X509_REQ *req, const ASN1_OBJECT *obj, int type, 283 const unsigned char *bytes, int len) 284 { 285 if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, 286 type, bytes, len)) 287 return 1; 288 return 0; 289 } 290 LCRYPTO_ALIAS(X509_REQ_add1_attr_by_OBJ); 291 292 int 293 X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, int type, 294 const unsigned char *bytes, int len) 295 { 296 if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, 297 type, bytes, len)) 298 return 1; 299 return 0; 300 } 301 LCRYPTO_ALIAS(X509_REQ_add1_attr_by_NID); 302 303 int 304 X509_REQ_add1_attr_by_txt(X509_REQ *req, const char *attrname, int type, 305 const unsigned char *bytes, int len) 306 { 307 if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, 308 type, bytes, len)) 309 return 1; 310 return 0; 311 } 312 LCRYPTO_ALIAS(X509_REQ_add1_attr_by_txt); 313 314 int 315 i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) 316 { 317 req->req_info->enc.modified = 1; 318 return i2d_X509_REQ_INFO(req->req_info, pp); 319 } 320 LCRYPTO_ALIAS(i2d_re_X509_REQ_tbs); 321