2 * Copyright 1999-2020 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/conf.h>
13 #include <openssl/asn1.h>
14 #include <openssl/asn1t.h>
15 #include <openssl/x509v3.h>
17 #include "x509_local.h"
18 #include "pcy_local.h"
21 DEFINE_STACK_OF(CONF_VALUE
)
22 DEFINE_STACK_OF(ASN1_INTEGER
)
24 /* Certificate policies extension support: this one is a bit complex... */
26 static int i2r_certpol(X509V3_EXT_METHOD
*method
, STACK_OF(POLICYINFO
) *pol
,
27 BIO
*out
, int indent
);
28 static STACK_OF(POLICYINFO
) *r2i_certpol(X509V3_EXT_METHOD
*method
,
29 X509V3_CTX
*ctx
, const char *value
);
30 static void print_qualifiers(BIO
*out
, STACK_OF(POLICYQUALINFO
) *quals
,
32 static void print_notice(BIO
*out
, USERNOTICE
*notice
, int indent
);
33 static POLICYINFO
*policy_section(X509V3_CTX
*ctx
,
34 STACK_OF(CONF_VALUE
) *polstrs
, int ia5org
);
35 static POLICYQUALINFO
*notice_section(X509V3_CTX
*ctx
,
36 STACK_OF(CONF_VALUE
) *unot
, int ia5org
);
37 static int nref_nos(STACK_OF(ASN1_INTEGER
) *nnums
, STACK_OF(CONF_VALUE
) *nos
);
38 static int displaytext_str2tag(const char *tagstr
, unsigned int *tag_len
);
39 static int displaytext_get_tag_len(const char *tagstr
);
41 const X509V3_EXT_METHOD v3_cpols
= {
42 NID_certificate_policies
, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES
),
46 (X509V3_EXT_I2R
)i2r_certpol
,
47 (X509V3_EXT_R2I
)r2i_certpol
,
51 ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES
) =
52 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF
, 0, CERTIFICATEPOLICIES
, POLICYINFO
)
53 ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES
)
55 IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES
)
57 ASN1_SEQUENCE(POLICYINFO
) = {
58 ASN1_SIMPLE(POLICYINFO
, policyid
, ASN1_OBJECT
),
59 ASN1_SEQUENCE_OF_OPT(POLICYINFO
, qualifiers
, POLICYQUALINFO
)
60 } ASN1_SEQUENCE_END(POLICYINFO
)
62 IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO
)
64 ASN1_ADB_TEMPLATE(policydefault
) = ASN1_SIMPLE(POLICYQUALINFO
, d
.other
, ASN1_ANY
);
66 ASN1_ADB(POLICYQUALINFO
) = {
67 ADB_ENTRY(NID_id_qt_cps
, ASN1_SIMPLE(POLICYQUALINFO
, d
.cpsuri
, ASN1_IA5STRING
)),
68 ADB_ENTRY(NID_id_qt_unotice
, ASN1_SIMPLE(POLICYQUALINFO
, d
.usernotice
, USERNOTICE
))
69 } ASN1_ADB_END(POLICYQUALINFO
, 0, pqualid
, 0, &policydefault_tt
, NULL
);
71 ASN1_SEQUENCE(POLICYQUALINFO
) = {
72 ASN1_SIMPLE(POLICYQUALINFO
, pqualid
, ASN1_OBJECT
),
73 ASN1_ADB_OBJECT(POLICYQUALINFO
)
74 } ASN1_SEQUENCE_END(POLICYQUALINFO
)
76 IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO
)
78 ASN1_SEQUENCE(USERNOTICE
) = {
79 ASN1_OPT(USERNOTICE
, noticeref
, NOTICEREF
),
80 ASN1_OPT(USERNOTICE
, exptext
, DISPLAYTEXT
)
81 } ASN1_SEQUENCE_END(USERNOTICE
)
83 IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE
)
85 ASN1_SEQUENCE(NOTICEREF
) = {
86 ASN1_SIMPLE(NOTICEREF
, organization
, DISPLAYTEXT
),
87 ASN1_SEQUENCE_OF(NOTICEREF
, noticenos
, ASN1_INTEGER
)
88 } ASN1_SEQUENCE_END(NOTICEREF
)
90 IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF
)
92 static STACK_OF(POLICYINFO
) *r2i_certpol(X509V3_EXT_METHOD
*method
,
93 X509V3_CTX
*ctx
, const char *value
)
95 STACK_OF(POLICYINFO
) *pols
;
99 STACK_OF(CONF_VALUE
) *vals
= X509V3_parse_list(value
);
101 const int num
= sk_CONF_VALUE_num(vals
);
105 X509V3err(X509V3_F_R2I_CERTPOL
, ERR_R_X509V3_LIB
);
109 pols
= sk_POLICYINFO_new_reserve(NULL
, num
);
111 X509V3err(X509V3_F_R2I_CERTPOL
, ERR_R_MALLOC_FAILURE
);
116 for (i
= 0; i
< num
; i
++) {
117 cnf
= sk_CONF_VALUE_value(vals
, i
);
118 if (cnf
->value
!= NULL
|| cnf
->name
== NULL
) {
119 X509V3err(X509V3_F_R2I_CERTPOL
,
120 X509V3_R_INVALID_POLICY_IDENTIFIER
);
121 X509V3_conf_add_error_name_value(cnf
);
125 if (strcmp(pstr
, "ia5org") == 0) {
128 } else if (*pstr
== '@') {
129 STACK_OF(CONF_VALUE
) *polsect
;
131 polsect
= X509V3_get_section(ctx
, pstr
+ 1);
132 if (polsect
== NULL
) {
133 X509V3err(X509V3_F_R2I_CERTPOL
, X509V3_R_INVALID_SECTION
);
134 ERR_add_error_data(1, cnf
->name
);
137 pol
= policy_section(ctx
, polsect
, ia5org
);
138 X509V3_section_free(ctx
, polsect
);
142 if ((pobj
= OBJ_txt2obj(cnf
->name
, 0)) == NULL
) {
143 X509V3err(X509V3_F_R2I_CERTPOL
,
144 X509V3_R_INVALID_OBJECT_IDENTIFIER
);
145 ERR_add_error_data(1, cnf
->name
);
148 pol
= POLICYINFO_new();
150 ASN1_OBJECT_free(pobj
);
151 X509V3err(X509V3_F_R2I_CERTPOL
, ERR_R_MALLOC_FAILURE
);
154 pol
->policyid
= pobj
;
156 if (!sk_POLICYINFO_push(pols
, pol
)) {
157 POLICYINFO_free(pol
);
158 X509V3err(X509V3_F_R2I_CERTPOL
, ERR_R_MALLOC_FAILURE
);
162 sk_CONF_VALUE_pop_free(vals
, X509V3_conf_free
);
165 sk_CONF_VALUE_pop_free(vals
, X509V3_conf_free
);
166 sk_POLICYINFO_pop_free(pols
, POLICYINFO_free
);
170 static POLICYINFO
*policy_section(X509V3_CTX
*ctx
,
171 STACK_OF(CONF_VALUE
) *polstrs
, int ia5org
)
176 POLICYQUALINFO
*qual
;
178 if ((pol
= POLICYINFO_new()) == NULL
)
180 for (i
= 0; i
< sk_CONF_VALUE_num(polstrs
); i
++) {
181 cnf
= sk_CONF_VALUE_value(polstrs
, i
);
182 if (strcmp(cnf
->name
, "policyIdentifier") == 0) {
185 if ((pobj
= OBJ_txt2obj(cnf
->value
, 0)) == NULL
) {
186 X509V3err(X509V3_F_POLICY_SECTION
,
187 X509V3_R_INVALID_OBJECT_IDENTIFIER
);
188 X509V3_conf_err(cnf
);
191 pol
->policyid
= pobj
;
193 } else if (!v3_name_cmp(cnf
->name
, "CPS")) {
194 if (pol
->qualifiers
== NULL
)
195 pol
->qualifiers
= sk_POLICYQUALINFO_new_null();
196 if ((qual
= POLICYQUALINFO_new()) == NULL
)
198 if (!sk_POLICYQUALINFO_push(pol
->qualifiers
, qual
))
200 if ((qual
->pqualid
= OBJ_nid2obj(NID_id_qt_cps
)) == NULL
) {
201 X509V3err(X509V3_F_POLICY_SECTION
, ERR_R_INTERNAL_ERROR
);
204 if ((qual
->d
.cpsuri
= ASN1_IA5STRING_new()) == NULL
)
206 if (!ASN1_STRING_set(qual
->d
.cpsuri
, cnf
->value
,
209 } else if (!v3_name_cmp(cnf
->name
, "userNotice")) {
210 STACK_OF(CONF_VALUE
) *unot
;
211 if (*cnf
->value
!= '@') {
212 X509V3err(X509V3_F_POLICY_SECTION
,
213 X509V3_R_EXPECTED_A_SECTION_NAME
);
214 X509V3_conf_err(cnf
);
217 unot
= X509V3_get_section(ctx
, cnf
->value
+ 1);
219 X509V3err(X509V3_F_POLICY_SECTION
, X509V3_R_INVALID_SECTION
);
221 X509V3_conf_err(cnf
);
224 qual
= notice_section(ctx
, unot
, ia5org
);
225 X509V3_section_free(ctx
, unot
);
228 if (pol
->qualifiers
== NULL
)
229 pol
->qualifiers
= sk_POLICYQUALINFO_new_null();
230 if (!sk_POLICYQUALINFO_push(pol
->qualifiers
, qual
))
233 X509V3err(X509V3_F_POLICY_SECTION
, X509V3_R_INVALID_OPTION
);
234 X509V3_conf_err(cnf
);
238 if (pol
->policyid
== NULL
) {
239 X509V3err(X509V3_F_POLICY_SECTION
, X509V3_R_NO_POLICY_IDENTIFIER
);
246 X509V3err(X509V3_F_POLICY_SECTION
, ERR_R_MALLOC_FAILURE
);
249 POLICYINFO_free(pol
);
253 static int displaytext_get_tag_len(const char *tagstr
)
255 char *colon
= strchr(tagstr
, ':');
257 return (colon
== NULL
) ? -1 : colon
- tagstr
;
260 static int displaytext_str2tag(const char *tagstr
, unsigned int *tag_len
)
265 len
= displaytext_get_tag_len(tagstr
);
268 return V_ASN1_VISIBLESTRING
;
270 if (len
== sizeof("UTF8") - 1 && strncmp(tagstr
, "UTF8", len
) == 0)
271 return V_ASN1_UTF8STRING
;
272 if (len
== sizeof("UTF8String") - 1 && strncmp(tagstr
, "UTF8String", len
) == 0)
273 return V_ASN1_UTF8STRING
;
274 if (len
== sizeof("BMP") - 1 && strncmp(tagstr
, "BMP", len
) == 0)
275 return V_ASN1_BMPSTRING
;
276 if (len
== sizeof("BMPSTRING") - 1 && strncmp(tagstr
, "BMPSTRING", len
) == 0)
277 return V_ASN1_BMPSTRING
;
278 if (len
== sizeof("VISIBLE") - 1 && strncmp(tagstr
, "VISIBLE", len
) == 0)
279 return V_ASN1_VISIBLESTRING
;
280 if (len
== sizeof("VISIBLESTRING") - 1 && strncmp(tagstr
, "VISIBLESTRING", len
) == 0)
281 return V_ASN1_VISIBLESTRING
;
283 return V_ASN1_VISIBLESTRING
;
286 static POLICYQUALINFO
*notice_section(X509V3_CTX
*ctx
,
287 STACK_OF(CONF_VALUE
) *unot
, int ia5org
)
289 int i
, ret
, len
, tag
;
290 unsigned int tag_len
;
293 POLICYQUALINFO
*qual
;
296 if ((qual
= POLICYQUALINFO_new()) == NULL
)
298 if ((qual
->pqualid
= OBJ_nid2obj(NID_id_qt_unotice
)) == NULL
) {
299 X509V3err(X509V3_F_NOTICE_SECTION
, ERR_R_INTERNAL_ERROR
);
302 if ((not = USERNOTICE_new()) == NULL
)
304 qual
->d
.usernotice
= not;
305 for (i
= 0; i
< sk_CONF_VALUE_num(unot
); i
++) {
306 cnf
= sk_CONF_VALUE_value(unot
, i
);
309 if (strcmp(cnf
->name
, "explicitText") == 0) {
310 tag
= displaytext_str2tag(value
, &tag_len
);
311 if ((not->exptext
= ASN1_STRING_type_new(tag
)) == NULL
)
314 value
+= tag_len
+ 1;
316 if (!ASN1_STRING_set(not->exptext
, value
, len
))
318 } else if (strcmp(cnf
->name
, "organization") == 0) {
321 if (!not->noticeref
) {
322 if ((nref
= NOTICEREF_new()) == NULL
)
324 not->noticeref
= nref
;
326 nref
= not->noticeref
;
328 nref
->organization
->type
= V_ASN1_IA5STRING
;
330 nref
->organization
->type
= V_ASN1_VISIBLESTRING
;
331 if (!ASN1_STRING_set(nref
->organization
, cnf
->value
,
334 } else if (strcmp(cnf
->name
, "noticeNumbers") == 0) {
337 STACK_OF(CONF_VALUE
) *nos
;
338 if (!not->noticeref
) {
339 if ((nref
= NOTICEREF_new()) == NULL
)
341 not->noticeref
= nref
;
343 nref
= not->noticeref
;
344 nos
= X509V3_parse_list(cnf
->value
);
345 if (!nos
|| !sk_CONF_VALUE_num(nos
)) {
346 X509V3err(X509V3_F_NOTICE_SECTION
, X509V3_R_INVALID_NUMBERS
);
347 X509V3_conf_add_error_name_value(cnf
);
348 sk_CONF_VALUE_pop_free(nos
, X509V3_conf_free
);
351 ret
= nref_nos(nref
->noticenos
, nos
);
352 sk_CONF_VALUE_pop_free(nos
, X509V3_conf_free
);
356 X509V3err(X509V3_F_NOTICE_SECTION
, X509V3_R_INVALID_OPTION
);
357 X509V3_conf_add_error_name_value(cnf
);
362 if (not->noticeref
&&
363 (!not->noticeref
->noticenos
|| !not->noticeref
->organization
)) {
364 X509V3err(X509V3_F_NOTICE_SECTION
,
365 X509V3_R_NEED_ORGANIZATION_AND_NUMBERS
);
372 X509V3err(X509V3_F_NOTICE_SECTION
, ERR_R_MALLOC_FAILURE
);
375 POLICYQUALINFO_free(qual
);
379 static int nref_nos(STACK_OF(ASN1_INTEGER
) *nnums
, STACK_OF(CONF_VALUE
) *nos
)
386 for (i
= 0; i
< sk_CONF_VALUE_num(nos
); i
++) {
387 cnf
= sk_CONF_VALUE_value(nos
, i
);
388 if ((aint
= s2i_ASN1_INTEGER(NULL
, cnf
->name
)) == NULL
) {
389 X509V3err(X509V3_F_NREF_NOS
, X509V3_R_INVALID_NUMBER
);
392 if (!sk_ASN1_INTEGER_push(nnums
, aint
))
398 ASN1_INTEGER_free(aint
);
399 X509V3err(X509V3_F_NREF_NOS
, ERR_R_MALLOC_FAILURE
);
405 static int i2r_certpol(X509V3_EXT_METHOD
*method
, STACK_OF(POLICYINFO
) *pol
,
406 BIO
*out
, int indent
)
410 /* First print out the policy OIDs */
411 for (i
= 0; i
< sk_POLICYINFO_num(pol
); i
++) {
414 pinfo
= sk_POLICYINFO_value(pol
, i
);
415 BIO_printf(out
, "%*sPolicy: ", indent
, "");
416 i2a_ASN1_OBJECT(out
, pinfo
->policyid
);
417 if (pinfo
->qualifiers
) {
419 print_qualifiers(out
, pinfo
->qualifiers
, indent
+ 2);
425 static void print_qualifiers(BIO
*out
, STACK_OF(POLICYQUALINFO
) *quals
,
428 POLICYQUALINFO
*qualinfo
;
430 for (i
= 0; i
< sk_POLICYQUALINFO_num(quals
); i
++) {
433 qualinfo
= sk_POLICYQUALINFO_value(quals
, i
);
434 switch (OBJ_obj2nid(qualinfo
->pqualid
)) {
436 BIO_printf(out
, "%*sCPS: %s", indent
, "",
437 qualinfo
->d
.cpsuri
->data
);
440 case NID_id_qt_unotice
:
441 BIO_printf(out
, "%*sUser Notice:\n", indent
, "");
442 print_notice(out
, qualinfo
->d
.usernotice
, indent
+ 2);
446 BIO_printf(out
, "%*sUnknown Qualifier: ", indent
+ 2, "");
448 i2a_ASN1_OBJECT(out
, qualinfo
->pqualid
);
454 static void print_notice(BIO
*out
, USERNOTICE
*notice
, int indent
)
457 if (notice
->noticeref
) {
459 ref
= notice
->noticeref
;
460 BIO_printf(out
, "%*sOrganization: %s\n", indent
, "",
461 ref
->organization
->data
);
462 BIO_printf(out
, "%*sNumber%s: ", indent
, "",
463 sk_ASN1_INTEGER_num(ref
->noticenos
) > 1 ? "s" : "");
464 for (i
= 0; i
< sk_ASN1_INTEGER_num(ref
->noticenos
); i
++) {
467 num
= sk_ASN1_INTEGER_value(ref
->noticenos
, i
);
471 BIO_puts(out
, "(null)");
473 tmp
= i2s_ASN1_INTEGER(NULL
, num
);
484 BIO_printf(out
, "%*sExplicit Text: %s", indent
, "",
485 notice
->exptext
->data
);
488 void X509_POLICY_NODE_print(BIO
*out
, X509_POLICY_NODE
*node
, int indent
)
490 const X509_POLICY_DATA
*dat
= node
->data
;
492 BIO_printf(out
, "%*sPolicy: ", indent
, "");
494 i2a_ASN1_OBJECT(out
, dat
->valid_policy
);
496 BIO_printf(out
, "%*s%s\n", indent
+ 2, "",
497 node_data_critical(dat
) ? "Critical" : "Non Critical");
498 if (dat
->qualifier_set
) {
499 print_qualifiers(out
, dat
->qualifier_set
, indent
+ 2);
503 BIO_printf(out
, "%*sNo Qualifiers\n", indent
+ 2, "");