1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2021 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/asn1t.h>
13e1051a39Sopenharmony_ci#include <openssl/x509.h>
14e1051a39Sopenharmony_ci#include "crypto/x509.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci/*-
17e1051a39Sopenharmony_ci * X509_REQ_INFO is handled in an unusual way to get round
18e1051a39Sopenharmony_ci * invalid encodings. Some broken certificate requests don't
19e1051a39Sopenharmony_ci * encode the attributes field if it is empty. This is in
20e1051a39Sopenharmony_ci * violation of PKCS#10 but we need to tolerate it. We do
21e1051a39Sopenharmony_ci * this by making the attributes field OPTIONAL then using
22e1051a39Sopenharmony_ci * the callback to initialise it to an empty STACK.
23e1051a39Sopenharmony_ci *
24e1051a39Sopenharmony_ci * This means that the field will be correctly encoded unless
25e1051a39Sopenharmony_ci * we NULL out the field.
26e1051a39Sopenharmony_ci *
27e1051a39Sopenharmony_ci * As a result we no longer need the req_kludge field because
28e1051a39Sopenharmony_ci * the information is now contained in the attributes field:
29e1051a39Sopenharmony_ci * 1. If it is NULL then it's the invalid omission.
30e1051a39Sopenharmony_ci * 2. If it is empty it is the correct encoding.
31e1051a39Sopenharmony_ci * 3. If it is not empty then some attributes are present.
32e1051a39Sopenharmony_ci *
33e1051a39Sopenharmony_ci */
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_cistatic int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
36e1051a39Sopenharmony_ci                   void *exarg)
37e1051a39Sopenharmony_ci{
38e1051a39Sopenharmony_ci    X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ci    if (operation == ASN1_OP_NEW_POST) {
41e1051a39Sopenharmony_ci        rinf->attributes = sk_X509_ATTRIBUTE_new_null();
42e1051a39Sopenharmony_ci        if (!rinf->attributes)
43e1051a39Sopenharmony_ci            return 0;
44e1051a39Sopenharmony_ci    }
45e1051a39Sopenharmony_ci    return 1;
46e1051a39Sopenharmony_ci}
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_cistatic int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
49e1051a39Sopenharmony_ci                  void *exarg)
50e1051a39Sopenharmony_ci{
51e1051a39Sopenharmony_ci    X509_REQ *ret = (X509_REQ *)*pval;
52e1051a39Sopenharmony_ci
53e1051a39Sopenharmony_ci    switch (operation) {
54e1051a39Sopenharmony_ci    case ASN1_OP_D2I_PRE:
55e1051a39Sopenharmony_ci        ASN1_OCTET_STRING_free(ret->distinguishing_id);
56e1051a39Sopenharmony_ci        /* fall thru */
57e1051a39Sopenharmony_ci    case ASN1_OP_NEW_POST:
58e1051a39Sopenharmony_ci        ret->distinguishing_id = NULL;
59e1051a39Sopenharmony_ci        break;
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_ci    case ASN1_OP_FREE_POST:
62e1051a39Sopenharmony_ci        ASN1_OCTET_STRING_free(ret->distinguishing_id);
63e1051a39Sopenharmony_ci        OPENSSL_free(ret->propq);
64e1051a39Sopenharmony_ci        break;
65e1051a39Sopenharmony_ci    case ASN1_OP_DUP_POST:
66e1051a39Sopenharmony_ci        {
67e1051a39Sopenharmony_ci            X509_REQ *old = exarg;
68e1051a39Sopenharmony_ci
69e1051a39Sopenharmony_ci            if (!ossl_x509_req_set0_libctx(ret, old->libctx, old->propq))
70e1051a39Sopenharmony_ci                return 0;
71e1051a39Sopenharmony_ci            if (old->req_info.pubkey != NULL) {
72e1051a39Sopenharmony_ci                EVP_PKEY *pkey = X509_PUBKEY_get0(old->req_info.pubkey);
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_ci                if (pkey != NULL) {
75e1051a39Sopenharmony_ci                    pkey = EVP_PKEY_dup(pkey);
76e1051a39Sopenharmony_ci                    if (pkey == NULL) {
77e1051a39Sopenharmony_ci                        ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
78e1051a39Sopenharmony_ci                        return 0;
79e1051a39Sopenharmony_ci                    }
80e1051a39Sopenharmony_ci                    if (!X509_PUBKEY_set(&ret->req_info.pubkey, pkey)) {
81e1051a39Sopenharmony_ci                        EVP_PKEY_free(pkey);
82e1051a39Sopenharmony_ci                        ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
83e1051a39Sopenharmony_ci                        return 0;
84e1051a39Sopenharmony_ci                    }
85e1051a39Sopenharmony_ci                    EVP_PKEY_free(pkey);
86e1051a39Sopenharmony_ci                }
87e1051a39Sopenharmony_ci            }
88e1051a39Sopenharmony_ci        }
89e1051a39Sopenharmony_ci        break;
90e1051a39Sopenharmony_ci    case ASN1_OP_GET0_LIBCTX:
91e1051a39Sopenharmony_ci        {
92e1051a39Sopenharmony_ci            OSSL_LIB_CTX **libctx = exarg;
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci            *libctx = ret->libctx;
95e1051a39Sopenharmony_ci        }
96e1051a39Sopenharmony_ci        break;
97e1051a39Sopenharmony_ci    case ASN1_OP_GET0_PROPQ:
98e1051a39Sopenharmony_ci        {
99e1051a39Sopenharmony_ci            const char **propq = exarg;
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci            *propq = ret->propq;
102e1051a39Sopenharmony_ci        }
103e1051a39Sopenharmony_ci        break;
104e1051a39Sopenharmony_ci    }
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ci    return 1;
107e1051a39Sopenharmony_ci}
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ciASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
110e1051a39Sopenharmony_ci        ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
111e1051a39Sopenharmony_ci        ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
112e1051a39Sopenharmony_ci        ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
113e1051a39Sopenharmony_ci        /* This isn't really OPTIONAL but it gets round invalid
114e1051a39Sopenharmony_ci         * encodings
115e1051a39Sopenharmony_ci         */
116e1051a39Sopenharmony_ci        ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
117e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)
118e1051a39Sopenharmony_ci
119e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ciASN1_SEQUENCE_ref(X509_REQ, req_cb) = {
122e1051a39Sopenharmony_ci        ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO),
123e1051a39Sopenharmony_ci        ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR),
124e1051a39Sopenharmony_ci        ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
125e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ)
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
128e1051a39Sopenharmony_ci
129e1051a39Sopenharmony_ciIMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_civoid X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *d_id)
132e1051a39Sopenharmony_ci{
133e1051a39Sopenharmony_ci    ASN1_OCTET_STRING_free(x->distinguishing_id);
134e1051a39Sopenharmony_ci    x->distinguishing_id = d_id;
135e1051a39Sopenharmony_ci}
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ciASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x)
138e1051a39Sopenharmony_ci{
139e1051a39Sopenharmony_ci    return x->distinguishing_id;
140e1051a39Sopenharmony_ci}
141e1051a39Sopenharmony_ci
142e1051a39Sopenharmony_ci/*
143e1051a39Sopenharmony_ci * This should only be used if the X509_REQ object was embedded inside another
144e1051a39Sopenharmony_ci * asn1 object and it needs a libctx to operate.
145e1051a39Sopenharmony_ci * Use X509_REQ_new_ex() instead if possible.
146e1051a39Sopenharmony_ci */
147e1051a39Sopenharmony_ciint ossl_x509_req_set0_libctx(X509_REQ *x, OSSL_LIB_CTX *libctx,
148e1051a39Sopenharmony_ci                              const char *propq)
149e1051a39Sopenharmony_ci{
150e1051a39Sopenharmony_ci    if (x != NULL) {
151e1051a39Sopenharmony_ci        x->libctx = libctx;
152e1051a39Sopenharmony_ci        OPENSSL_free(x->propq);
153e1051a39Sopenharmony_ci        x->propq = NULL;
154e1051a39Sopenharmony_ci        if (propq != NULL) {
155e1051a39Sopenharmony_ci            x->propq = OPENSSL_strdup(propq);
156e1051a39Sopenharmony_ci            if (x->propq == NULL)
157e1051a39Sopenharmony_ci                return 0;
158e1051a39Sopenharmony_ci        }
159e1051a39Sopenharmony_ci    }
160e1051a39Sopenharmony_ci    return 1;
161e1051a39Sopenharmony_ci}
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_ciX509_REQ *X509_REQ_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
164e1051a39Sopenharmony_ci{
165e1051a39Sopenharmony_ci    X509_REQ *req = NULL;
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ci    req = (X509_REQ *)ASN1_item_new((X509_REQ_it()));
168e1051a39Sopenharmony_ci    if (!ossl_x509_req_set0_libctx(req, libctx, propq)) {
169e1051a39Sopenharmony_ci        X509_REQ_free(req);
170e1051a39Sopenharmony_ci        req = NULL;
171e1051a39Sopenharmony_ci    }
172e1051a39Sopenharmony_ci    return req;
173e1051a39Sopenharmony_ci}
174