]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/x509/x_req.c
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
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
11 #include "internal/cryptlib.h"
12 #include <openssl/asn1t.h>
13 #include <openssl/x509.h>
14 #include "crypto/x509.h"
17 * X509_REQ_INFO is handled in an unusual way to get round
18 * invalid encodings. Some broken certificate requests don't
19 * encode the attributes field if it is empty. This is in
20 * violation of PKCS#10 but we need to tolerate it. We do
21 * this by making the attributes field OPTIONAL then using
22 * the callback to initialise it to an empty STACK.
24 * This means that the field will be correctly encoded unless
25 * we NULL out the field.
27 * As a result we no longer need the req_kludge field because
28 * the information is now contained in the attributes field:
29 * 1. If it is NULL then it's the invalid omission.
30 * 2. If it is empty it is the correct encoding.
31 * 3. If it is not empty then some attributes are present.
35 static int rinf_cb(int operation
, ASN1_VALUE
**pval
, const ASN1_ITEM
*it
,
38 X509_REQ_INFO
*rinf
= (X509_REQ_INFO
*)*pval
;
40 if (operation
== ASN1_OP_NEW_POST
) {
41 rinf
->attributes
= sk_X509_ATTRIBUTE_new_null();
42 if (!rinf
->attributes
)
48 static int req_cb(int operation
, ASN1_VALUE
**pval
, const ASN1_ITEM
*it
,
51 X509_REQ
*ret
= (X509_REQ
*)*pval
;
55 ASN1_OCTET_STRING_free(ret
->distinguishing_id
);
57 case ASN1_OP_NEW_POST
:
58 ret
->distinguishing_id
= NULL
;
61 case ASN1_OP_FREE_POST
:
62 ASN1_OCTET_STRING_free(ret
->distinguishing_id
);
63 OPENSSL_free(ret
->propq
);
65 case ASN1_OP_DUP_POST
:
67 X509_REQ
*old
= exarg
;
69 if (!ossl_x509_req_set0_libctx(ret
, old
->libctx
, old
->propq
))
71 if (old
->req_info
.pubkey
!= NULL
) {
72 EVP_PKEY
*pkey
= X509_PUBKEY_get0(old
->req_info
.pubkey
);
75 pkey
= EVP_PKEY_dup(pkey
);
77 ERR_raise(ERR_LIB_X509
, ERR_R_EVP_LIB
);
80 if (!X509_PUBKEY_set(&ret
->req_info
.pubkey
, pkey
)) {
82 ERR_raise(ERR_LIB_X509
, ERR_R_INTERNAL_ERROR
);
90 case ASN1_OP_GET0_LIBCTX
:
92 OSSL_LIB_CTX
**libctx
= exarg
;
94 *libctx
= ret
->libctx
;
97 case ASN1_OP_GET0_PROPQ
:
99 const char **propq
= exarg
;
109 ASN1_SEQUENCE_enc(X509_REQ_INFO
, enc
, rinf_cb
) = {
110 ASN1_SIMPLE(X509_REQ_INFO
, version
, ASN1_INTEGER
),
111 ASN1_SIMPLE(X509_REQ_INFO
, subject
, X509_NAME
),
112 ASN1_SIMPLE(X509_REQ_INFO
, pubkey
, X509_PUBKEY
),
113 /* This isn't really OPTIONAL but it gets round invalid
116 ASN1_IMP_SET_OF_OPT(X509_REQ_INFO
, attributes
, X509_ATTRIBUTE
, 0)
117 } ASN1_SEQUENCE_END_enc(X509_REQ_INFO
, X509_REQ_INFO
)
119 IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO
)
121 ASN1_SEQUENCE_ref(X509_REQ
, req_cb
) = {
122 ASN1_EMBED(X509_REQ
, req_info
, X509_REQ_INFO
),
123 ASN1_EMBED(X509_REQ
, sig_alg
, X509_ALGOR
),
124 ASN1_SIMPLE(X509_REQ
, signature
, ASN1_BIT_STRING
)
125 } ASN1_SEQUENCE_END_ref(X509_REQ
, X509_REQ
)
127 IMPLEMENT_ASN1_FUNCTIONS(X509_REQ
)
129 IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ
)
131 void X509_REQ_set0_distinguishing_id(X509_REQ
*x
, ASN1_OCTET_STRING
*d_id
)
133 ASN1_OCTET_STRING_free(x
->distinguishing_id
);
134 x
->distinguishing_id
= d_id
;
137 ASN1_OCTET_STRING
*X509_REQ_get0_distinguishing_id(X509_REQ
*x
)
139 return x
->distinguishing_id
;
143 * This should only be used if the X509_REQ object was embedded inside another
144 * asn1 object and it needs a libctx to operate.
145 * Use X509_REQ_new_ex() instead if possible.
147 int ossl_x509_req_set0_libctx(X509_REQ
*x
, OSSL_LIB_CTX
*libctx
,
152 OPENSSL_free(x
->propq
);
155 x
->propq
= OPENSSL_strdup(propq
);
156 if (x
->propq
== NULL
)
163 X509_REQ
*X509_REQ_new_ex(OSSL_LIB_CTX
*libctx
, const char *propq
)
165 X509_REQ
*req
= NULL
;
167 req
= (X509_REQ
*)ASN1_item_new((X509_REQ_it()));
168 if (!ossl_x509_req_set0_libctx(req
, libctx
, propq
)) {