diff options
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_purp.c')
-rw-r--r-- | src/lib/libcrypto/x509v3/v3_purp.c | 194 |
1 files changed, 149 insertions, 45 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_purp.c b/src/lib/libcrypto/x509v3/v3_purp.c index e18751e01c..181bd34979 100644 --- a/src/lib/libcrypto/x509v3/v3_purp.c +++ b/src/lib/libcrypto/x509v3/v3_purp.c | |||
@@ -71,6 +71,7 @@ static int purpose_smime(const X509 *x, int ca); | |||
71 | static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca); | 71 | static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca); |
72 | static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca); | 72 | static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca); |
73 | static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca); | 73 | static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca); |
74 | static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca); | ||
74 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); | 75 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); |
75 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); | 76 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); |
76 | 77 | ||
@@ -87,6 +88,7 @@ static X509_PURPOSE xstandard[] = { | |||
87 | {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL}, | 88 | {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL}, |
88 | {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL}, | 89 | {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL}, |
89 | {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL}, | 90 | {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL}, |
91 | {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign", NULL}, | ||
90 | }; | 92 | }; |
91 | 93 | ||
92 | #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) | 94 | #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) |
@@ -265,11 +267,14 @@ int X509_PURPOSE_get_trust(X509_PURPOSE *xp) | |||
265 | return xp->trust; | 267 | return xp->trust; |
266 | } | 268 | } |
267 | 269 | ||
268 | static int nid_cmp(int *a, int *b) | 270 | static int nid_cmp(const int *a, const int *b) |
269 | { | 271 | { |
270 | return *a - *b; | 272 | return *a - *b; |
271 | } | 273 | } |
272 | 274 | ||
275 | DECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid); | ||
276 | IMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid); | ||
277 | |||
273 | int X509_supported_extension(X509_EXTENSION *ex) | 278 | int X509_supported_extension(X509_EXTENSION *ex) |
274 | { | 279 | { |
275 | /* This table is a list of the NIDs of supported extensions: | 280 | /* This table is a list of the NIDs of supported extensions: |
@@ -280,7 +285,7 @@ int X509_supported_extension(X509_EXTENSION *ex) | |||
280 | * searched using bsearch. | 285 | * searched using bsearch. |
281 | */ | 286 | */ |
282 | 287 | ||
283 | static int supported_nids[] = { | 288 | static const int supported_nids[] = { |
284 | NID_netscape_cert_type, /* 71 */ | 289 | NID_netscape_cert_type, /* 71 */ |
285 | NID_key_usage, /* 83 */ | 290 | NID_key_usage, /* 83 */ |
286 | NID_subject_alt_name, /* 85 */ | 291 | NID_subject_alt_name, /* 85 */ |
@@ -292,24 +297,62 @@ int X509_supported_extension(X509_EXTENSION *ex) | |||
292 | NID_sbgp_autonomousSysNum, /* 291 */ | 297 | NID_sbgp_autonomousSysNum, /* 291 */ |
293 | #endif | 298 | #endif |
294 | NID_policy_constraints, /* 401 */ | 299 | NID_policy_constraints, /* 401 */ |
295 | NID_proxyCertInfo, /* 661 */ | 300 | NID_proxyCertInfo, /* 663 */ |
301 | NID_name_constraints, /* 666 */ | ||
302 | NID_policy_mappings, /* 747 */ | ||
296 | NID_inhibit_any_policy /* 748 */ | 303 | NID_inhibit_any_policy /* 748 */ |
297 | }; | 304 | }; |
298 | 305 | ||
299 | int ex_nid; | 306 | int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); |
300 | |||
301 | ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); | ||
302 | 307 | ||
303 | if (ex_nid == NID_undef) | 308 | if (ex_nid == NID_undef) |
304 | return 0; | 309 | return 0; |
305 | 310 | ||
306 | if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids, | 311 | if (OBJ_bsearch_nid(&ex_nid, supported_nids, |
307 | sizeof(supported_nids)/sizeof(int), sizeof(int), | 312 | sizeof(supported_nids)/sizeof(int))) |
308 | (int (*)(const void *, const void *))nid_cmp)) | ||
309 | return 1; | 313 | return 1; |
310 | return 0; | 314 | return 0; |
311 | } | 315 | } |
312 | 316 | ||
317 | static void setup_dp(X509 *x, DIST_POINT *dp) | ||
318 | { | ||
319 | X509_NAME *iname = NULL; | ||
320 | int i; | ||
321 | if (dp->reasons) | ||
322 | { | ||
323 | if (dp->reasons->length > 0) | ||
324 | dp->dp_reasons = dp->reasons->data[0]; | ||
325 | if (dp->reasons->length > 1) | ||
326 | dp->dp_reasons |= (dp->reasons->data[1] << 8); | ||
327 | dp->dp_reasons &= CRLDP_ALL_REASONS; | ||
328 | } | ||
329 | else | ||
330 | dp->dp_reasons = CRLDP_ALL_REASONS; | ||
331 | if (!dp->distpoint || (dp->distpoint->type != 1)) | ||
332 | return; | ||
333 | for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) | ||
334 | { | ||
335 | GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); | ||
336 | if (gen->type == GEN_DIRNAME) | ||
337 | { | ||
338 | iname = gen->d.directoryName; | ||
339 | break; | ||
340 | } | ||
341 | } | ||
342 | if (!iname) | ||
343 | iname = X509_get_issuer_name(x); | ||
344 | |||
345 | DIST_POINT_set_dpname(dp->distpoint, iname); | ||
346 | |||
347 | } | ||
348 | |||
349 | static void setup_crldp(X509 *x) | ||
350 | { | ||
351 | int i; | ||
352 | x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); | ||
353 | for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) | ||
354 | setup_dp(x, sk_DIST_POINT_value(x->crldp, i)); | ||
355 | } | ||
313 | 356 | ||
314 | static void x509v3_cache_extensions(X509 *x) | 357 | static void x509v3_cache_extensions(X509 *x) |
315 | { | 358 | { |
@@ -417,16 +460,25 @@ static void x509v3_cache_extensions(X509 *x) | |||
417 | } | 460 | } |
418 | x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); | 461 | x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); |
419 | x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); | 462 | x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); |
463 | x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); | ||
464 | x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL); | ||
465 | if (!x->nc && (i != -1)) | ||
466 | x->ex_flags |= EXFLAG_INVALID; | ||
467 | setup_crldp(x); | ||
468 | |||
420 | #ifndef OPENSSL_NO_RFC3779 | 469 | #ifndef OPENSSL_NO_RFC3779 |
421 | x->rfc3779_addr =X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); | 470 | x->rfc3779_addr =X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); |
422 | x->rfc3779_asid =X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, | 471 | x->rfc3779_asid =X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, |
423 | NULL, NULL); | 472 | NULL, NULL); |
424 | #endif | 473 | #endif |
425 | for (i = 0; i < X509_get_ext_count(x); i++) | 474 | for (i = 0; i < X509_get_ext_count(x); i++) |
426 | { | 475 | { |
427 | ex = X509_get_ext(x, i); | 476 | ex = X509_get_ext(x, i); |
428 | if (!X509_EXTENSION_get_critical(ex)) | 477 | if (!X509_EXTENSION_get_critical(ex)) |
429 | continue; | 478 | continue; |
479 | if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) | ||
480 | == NID_freshest_crl) | ||
481 | x->ex_flags |= EXFLAG_FRESHEST; | ||
430 | if (!X509_supported_extension(ex)) | 482 | if (!X509_supported_extension(ex)) |
431 | { | 483 | { |
432 | x->ex_flags |= EXFLAG_CRITICAL; | 484 | x->ex_flags |= EXFLAG_CRITICAL; |
@@ -594,6 +646,41 @@ static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) | |||
594 | return 1; | 646 | return 1; |
595 | } | 647 | } |
596 | 648 | ||
649 | static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, | ||
650 | int ca) | ||
651 | { | ||
652 | int i_ext; | ||
653 | |||
654 | /* If ca is true we must return if this is a valid CA certificate. */ | ||
655 | if (ca) return check_ca(x); | ||
656 | |||
657 | /* | ||
658 | * Check the optional key usage field: | ||
659 | * if Key Usage is present, it must be one of digitalSignature | ||
660 | * and/or nonRepudiation (other values are not consistent and shall | ||
661 | * be rejected). | ||
662 | */ | ||
663 | if ((x->ex_flags & EXFLAG_KUSAGE) | ||
664 | && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || | ||
665 | !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) | ||
666 | return 0; | ||
667 | |||
668 | /* Only time stamp key usage is permitted and it's required. */ | ||
669 | if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) | ||
670 | return 0; | ||
671 | |||
672 | /* Extended Key Usage MUST be critical */ | ||
673 | i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, 0); | ||
674 | if (i_ext >= 0) | ||
675 | { | ||
676 | X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext); | ||
677 | if (!X509_EXTENSION_get_critical(ext)) | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | return 1; | ||
682 | } | ||
683 | |||
597 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) | 684 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) |
598 | { | 685 | { |
599 | return 1; | 686 | return 1; |
@@ -618,39 +705,14 @@ int X509_check_issued(X509 *issuer, X509 *subject) | |||
618 | return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; | 705 | return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; |
619 | x509v3_cache_extensions(issuer); | 706 | x509v3_cache_extensions(issuer); |
620 | x509v3_cache_extensions(subject); | 707 | x509v3_cache_extensions(subject); |
621 | if(subject->akid) { | 708 | |
622 | /* Check key ids (if present) */ | 709 | if(subject->akid) |
623 | if(subject->akid->keyid && issuer->skid && | 710 | { |
624 | ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid) ) | 711 | int ret = X509_check_akid(issuer, subject->akid); |
625 | return X509_V_ERR_AKID_SKID_MISMATCH; | 712 | if (ret != X509_V_OK) |
626 | /* Check serial number */ | 713 | return ret; |
627 | if(subject->akid->serial && | ||
628 | ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), | ||
629 | subject->akid->serial)) | ||
630 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; | ||
631 | /* Check issuer name */ | ||
632 | if(subject->akid->issuer) { | ||
633 | /* Ugh, for some peculiar reason AKID includes | ||
634 | * SEQUENCE OF GeneralName. So look for a DirName. | ||
635 | * There may be more than one but we only take any | ||
636 | * notice of the first. | ||
637 | */ | ||
638 | GENERAL_NAMES *gens; | ||
639 | GENERAL_NAME *gen; | ||
640 | X509_NAME *nm = NULL; | ||
641 | int i; | ||
642 | gens = subject->akid->issuer; | ||
643 | for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) { | ||
644 | gen = sk_GENERAL_NAME_value(gens, i); | ||
645 | if(gen->type == GEN_DIRNAME) { | ||
646 | nm = gen->d.dirn; | ||
647 | break; | ||
648 | } | ||
649 | } | ||
650 | if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) | ||
651 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; | ||
652 | } | 714 | } |
653 | } | 715 | |
654 | if(subject->ex_flags & EXFLAG_PROXY) | 716 | if(subject->ex_flags & EXFLAG_PROXY) |
655 | { | 717 | { |
656 | if(ku_reject(issuer, KU_DIGITAL_SIGNATURE)) | 718 | if(ku_reject(issuer, KU_DIGITAL_SIGNATURE)) |
@@ -661,3 +723,45 @@ int X509_check_issued(X509 *issuer, X509 *subject) | |||
661 | return X509_V_OK; | 723 | return X509_V_OK; |
662 | } | 724 | } |
663 | 725 | ||
726 | int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) | ||
727 | { | ||
728 | |||
729 | if(!akid) | ||
730 | return X509_V_OK; | ||
731 | |||
732 | /* Check key ids (if present) */ | ||
733 | if(akid->keyid && issuer->skid && | ||
734 | ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid) ) | ||
735 | return X509_V_ERR_AKID_SKID_MISMATCH; | ||
736 | /* Check serial number */ | ||
737 | if(akid->serial && | ||
738 | ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) | ||
739 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; | ||
740 | /* Check issuer name */ | ||
741 | if(akid->issuer) | ||
742 | { | ||
743 | /* Ugh, for some peculiar reason AKID includes | ||
744 | * SEQUENCE OF GeneralName. So look for a DirName. | ||
745 | * There may be more than one but we only take any | ||
746 | * notice of the first. | ||
747 | */ | ||
748 | GENERAL_NAMES *gens; | ||
749 | GENERAL_NAME *gen; | ||
750 | X509_NAME *nm = NULL; | ||
751 | int i; | ||
752 | gens = akid->issuer; | ||
753 | for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) | ||
754 | { | ||
755 | gen = sk_GENERAL_NAME_value(gens, i); | ||
756 | if(gen->type == GEN_DIRNAME) | ||
757 | { | ||
758 | nm = gen->d.dirn; | ||
759 | break; | ||
760 | } | ||
761 | } | ||
762 | if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) | ||
763 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; | ||
764 | } | ||
765 | return X509_V_OK; | ||
766 | } | ||
767 | |||