Remove X509_REQ_set_extension_nids and document related functions.
PKCS#10 CSRs don't contain extensions but attributes, which are kind of
like extensions, but defined separately. There is an attribute type from
PKCS#9 to embed a list of X.509 extensions inside an attribute, as well
as a Microsoft variant.
X509_REQ_set_extension_nids allowed callers globally reconfigure the set
of attributes recognized as aliases of this extensions attribute. This
is not used by anyone and not thread-safe. Remove it and only support
the two default attribute types.
From there, document the remaining functions.
Update-Note: This removes a pair of unused functions.
Change-Id: Ic1fc41163996c0c980ba8320b417e444d484aa39
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46326
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c
index d7da620..719257e 100644
--- a/crypto/x509/x509_req.c
+++ b/crypto/x509/x509_req.c
@@ -157,62 +157,37 @@
return (ok);
}
-/*
- * It seems several organisations had the same idea of including a list of
- * extensions in a certificate request. There are at least two OIDs that are
- * used and there may be more: so the list is configurable.
- */
-
-static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef };
-
-static const int *ext_nids = ext_nid_list;
-
int X509_REQ_extension_nid(int req_nid)
{
- int i, nid;
- for (i = 0;; i++) {
- nid = ext_nids[i];
- if (nid == NID_undef)
- return 0;
- else if (req_nid == nid)
- return 1;
- }
-}
-
-const int *X509_REQ_get_extension_nids(void)
-{
- return ext_nids;
-}
-
-void X509_REQ_set_extension_nids(const int *nids)
-{
- ext_nids = nids;
+ return req_nid == NID_ext_req || req_nid == NID_ms_ext_req;
}
STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
{
- X509_ATTRIBUTE *attr;
- ASN1_TYPE *ext = NULL;
- int idx;
- const int *pnid;
- const unsigned char *p;
-
- if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
- return (NULL);
- for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
- idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
- if (idx == -1)
- continue;
- attr = X509_REQ_get_attr(req, idx);
- if (attr->single)
- ext = attr->value.single;
- else if (sk_ASN1_TYPE_num(attr->value.set))
- ext = sk_ASN1_TYPE_value(attr->value.set, 0);
- break;
- }
- if (!ext || (ext->type != V_ASN1_SEQUENCE))
+ if (req == NULL || req->req_info == NULL) {
return NULL;
- p = ext->value.sequence->data;
+ }
+
+ int idx = X509_REQ_get_attr_by_NID(req, NID_ext_req, -1);
+ if (idx == -1) {
+ idx = X509_REQ_get_attr_by_NID(req, NID_ms_ext_req, -1);
+ }
+ if (idx == -1) {
+ return NULL;
+ }
+
+ X509_ATTRIBUTE *attr = X509_REQ_get_attr(req, idx);
+ ASN1_TYPE *ext = NULL;
+ if (attr->single) {
+ ext = attr->value.single;
+ } else if (sk_ASN1_TYPE_num(attr->value.set)) {
+ ext = sk_ASN1_TYPE_value(attr->value.set, 0);
+ }
+
+ if (!ext || ext->type != V_ASN1_SEQUENCE) {
+ return NULL;
+ }
+ const unsigned char *p = ext->value.sequence->data;
return (STACK_OF(X509_EXTENSION) *)
ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
ASN1_ITEM_rptr(X509_EXTENSIONS));
@@ -223,8 +198,8 @@
* in case we want to create a non standard one.
*/
-int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
- int nid)
+int X509_REQ_add_extensions_nid(X509_REQ *req,
+ const STACK_OF(X509_EXTENSION) *exts, int nid)
{
ASN1_TYPE *at = NULL;
X509_ATTRIBUTE *attr = NULL;
@@ -260,7 +235,8 @@
}
/* This is the normal usage: use the "official" OID */
-int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
+int X509_REQ_add_extensions(X509_REQ *req,
+ const STACK_OF(X509_EXTENSION) *exts)
{
return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
}
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 11a61b7..714a8eb 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -1239,15 +1239,31 @@
// |EVP_PKEY_free| when done.
OPENSSL_EXPORT EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req);
+// X509_REQ_extension_nid returns one if |nid| is a supported CSR attribute type
+// for carrying extensions and zero otherwise. The supported types are
+// |NID_ext_req| (pkcs-9-at-extensionRequest from RFC2985) and |NID_ms_ext_req|
+// (a Microsoft szOID_CERT_EXTENSIONS variant).
OPENSSL_EXPORT int X509_REQ_extension_nid(int nid);
-OPENSSL_EXPORT const int *X509_REQ_get_extension_nids(void);
-OPENSSL_EXPORT void X509_REQ_set_extension_nids(const int *nids);
+
+// X509_REQ_get_extensions decodes the list of requested extensions in |req| and
+// returns a newly-allocated |STACK_OF(X509_EXTENSION)| containing the result.
+// It returns NULL on error, or if |req| did not request extensions.
+//
+// This function supports both pkcs-9-at-extensionRequest from RFC2985 and the
+// Microsoft szOID_CERT_EXTENSIONS variant.
OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
-OPENSSL_EXPORT int X509_REQ_add_extensions_nid(X509_REQ *req,
- STACK_OF(X509_EXTENSION) *exts,
- int nid);
-OPENSSL_EXPORT int X509_REQ_add_extensions(X509_REQ *req,
- STACK_OF(X509_EXTENSION) *exts);
+
+// X509_REQ_add_extensions_nid adds an attribute to |req| of type |nid|, to
+// request the certificate extensions in |exts|. It returns one on success and
+// zero on error. |nid| should be |NID_ext_req| or |NID_ms_ext_req|.
+OPENSSL_EXPORT int X509_REQ_add_extensions_nid(
+ X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts, int nid);
+
+// X509_REQ_add_extensions behaves like |X509_REQ_add_extensions_nid|, using the
+// standard |NID_ext_req| for the attribute type.
+OPENSSL_EXPORT int X509_REQ_add_extensions(
+ X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts);
+
OPENSSL_EXPORT int X509_REQ_get_attr_count(const X509_REQ *req);
OPENSSL_EXPORT int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
int lastpos);