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