| Index: openssl/crypto/x509v3/v3_purp.c
|
| ===================================================================
|
| --- openssl/crypto/x509v3/v3_purp.c (revision 105093)
|
| +++ openssl/crypto/x509v3/v3_purp.c (working copy)
|
| @@ -71,6 +71,7 @@
|
| static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
|
| static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca);
|
| static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
|
| +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
|
| static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
|
| static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
|
|
|
| @@ -87,6 +88,7 @@
|
| {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL},
|
| {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL},
|
| {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL},
|
| + {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign", NULL},
|
| };
|
|
|
| #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE))
|
| @@ -265,11 +267,14 @@
|
| return xp->trust;
|
| }
|
|
|
| -static int nid_cmp(int *a, int *b)
|
| +static int nid_cmp(const int *a, const int *b)
|
| {
|
| return *a - *b;
|
| }
|
|
|
| +DECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid);
|
| +IMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid);
|
| +
|
| int X509_supported_extension(X509_EXTENSION *ex)
|
| {
|
| /* This table is a list of the NIDs of supported extensions:
|
| @@ -280,7 +285,7 @@
|
| * searched using bsearch.
|
| */
|
|
|
| - static int supported_nids[] = {
|
| + static const int supported_nids[] = {
|
| NID_netscape_cert_type, /* 71 */
|
| NID_key_usage, /* 83 */
|
| NID_subject_alt_name, /* 85 */
|
| @@ -292,25 +297,63 @@
|
| NID_sbgp_autonomousSysNum, /* 291 */
|
| #endif
|
| NID_policy_constraints, /* 401 */
|
| - NID_proxyCertInfo, /* 661 */
|
| + NID_proxyCertInfo, /* 663 */
|
| + NID_name_constraints, /* 666 */
|
| + NID_policy_mappings, /* 747 */
|
| NID_inhibit_any_policy /* 748 */
|
| };
|
|
|
| - int ex_nid;
|
| + int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
|
|
|
| - ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
|
| -
|
| if (ex_nid == NID_undef)
|
| return 0;
|
|
|
| - if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids,
|
| - sizeof(supported_nids)/sizeof(int), sizeof(int),
|
| - (int (*)(const void *, const void *))nid_cmp))
|
| + if (OBJ_bsearch_nid(&ex_nid, supported_nids,
|
| + sizeof(supported_nids)/sizeof(int)))
|
| return 1;
|
| return 0;
|
| }
|
| -
|
|
|
| +static void setup_dp(X509 *x, DIST_POINT *dp)
|
| + {
|
| + X509_NAME *iname = NULL;
|
| + int i;
|
| + if (dp->reasons)
|
| + {
|
| + if (dp->reasons->length > 0)
|
| + dp->dp_reasons = dp->reasons->data[0];
|
| + if (dp->reasons->length > 1)
|
| + dp->dp_reasons |= (dp->reasons->data[1] << 8);
|
| + dp->dp_reasons &= CRLDP_ALL_REASONS;
|
| + }
|
| + else
|
| + dp->dp_reasons = CRLDP_ALL_REASONS;
|
| + if (!dp->distpoint || (dp->distpoint->type != 1))
|
| + return;
|
| + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
|
| + {
|
| + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
|
| + if (gen->type == GEN_DIRNAME)
|
| + {
|
| + iname = gen->d.directoryName;
|
| + break;
|
| + }
|
| + }
|
| + if (!iname)
|
| + iname = X509_get_issuer_name(x);
|
| +
|
| + DIST_POINT_set_dpname(dp->distpoint, iname);
|
| +
|
| + }
|
| +
|
| +static void setup_crldp(X509 *x)
|
| + {
|
| + int i;
|
| + x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
|
| + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
|
| + setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
|
| + }
|
| +
|
| static void x509v3_cache_extensions(X509 *x)
|
| {
|
| BASIC_CONSTRAINTS *bs;
|
| @@ -417,16 +460,25 @@
|
| }
|
| x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
|
| x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
|
| + x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
|
| + x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
|
| + if (!x->nc && (i != -1))
|
| + x->ex_flags |= EXFLAG_INVALID;
|
| + setup_crldp(x);
|
| +
|
| #ifndef OPENSSL_NO_RFC3779
|
| - x->rfc3779_addr =X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL);
|
| - x->rfc3779_asid =X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum,
|
| - NULL, NULL);
|
| + x->rfc3779_addr =X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL);
|
| + x->rfc3779_asid =X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum,
|
| + NULL, NULL);
|
| #endif
|
| for (i = 0; i < X509_get_ext_count(x); i++)
|
| {
|
| ex = X509_get_ext(x, i);
|
| if (!X509_EXTENSION_get_critical(ex))
|
| continue;
|
| + if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
|
| + == NID_freshest_crl)
|
| + x->ex_flags |= EXFLAG_FRESHEST;
|
| if (!X509_supported_extension(ex))
|
| {
|
| x->ex_flags |= EXFLAG_CRITICAL;
|
| @@ -594,6 +646,41 @@
|
| return 1;
|
| }
|
|
|
| +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
|
| + int ca)
|
| +{
|
| + int i_ext;
|
| +
|
| + /* If ca is true we must return if this is a valid CA certificate. */
|
| + if (ca) return check_ca(x);
|
| +
|
| + /*
|
| + * Check the optional key usage field:
|
| + * if Key Usage is present, it must be one of digitalSignature
|
| + * and/or nonRepudiation (other values are not consistent and shall
|
| + * be rejected).
|
| + */
|
| + if ((x->ex_flags & EXFLAG_KUSAGE)
|
| + && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
|
| + !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
|
| + return 0;
|
| +
|
| + /* Only time stamp key usage is permitted and it's required. */
|
| + if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
|
| + return 0;
|
| +
|
| + /* Extended Key Usage MUST be critical */
|
| + i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, 0);
|
| + if (i_ext >= 0)
|
| + {
|
| + X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext);
|
| + if (!X509_EXTENSION_get_critical(ext))
|
| + return 0;
|
| + }
|
| +
|
| + return 1;
|
| +}
|
| +
|
| static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
|
| {
|
| return 1;
|
| @@ -618,39 +705,14 @@
|
| return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
|
| x509v3_cache_extensions(issuer);
|
| x509v3_cache_extensions(subject);
|
| - if(subject->akid) {
|
| - /* Check key ids (if present) */
|
| - if(subject->akid->keyid && issuer->skid &&
|
| - ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid) )
|
| - return X509_V_ERR_AKID_SKID_MISMATCH;
|
| - /* Check serial number */
|
| - if(subject->akid->serial &&
|
| - ASN1_INTEGER_cmp(X509_get_serialNumber(issuer),
|
| - subject->akid->serial))
|
| - return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
|
| - /* Check issuer name */
|
| - if(subject->akid->issuer) {
|
| - /* Ugh, for some peculiar reason AKID includes
|
| - * SEQUENCE OF GeneralName. So look for a DirName.
|
| - * There may be more than one but we only take any
|
| - * notice of the first.
|
| - */
|
| - GENERAL_NAMES *gens;
|
| - GENERAL_NAME *gen;
|
| - X509_NAME *nm = NULL;
|
| - int i;
|
| - gens = subject->akid->issuer;
|
| - for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
|
| - gen = sk_GENERAL_NAME_value(gens, i);
|
| - if(gen->type == GEN_DIRNAME) {
|
| - nm = gen->d.dirn;
|
| - break;
|
| - }
|
| - }
|
| - if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
|
| - return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
|
| +
|
| + if(subject->akid)
|
| + {
|
| + int ret = X509_check_akid(issuer, subject->akid);
|
| + if (ret != X509_V_OK)
|
| + return ret;
|
| }
|
| - }
|
| +
|
| if(subject->ex_flags & EXFLAG_PROXY)
|
| {
|
| if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
|
| @@ -661,3 +723,45 @@
|
| return X509_V_OK;
|
| }
|
|
|
| +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
|
| + {
|
| +
|
| + if(!akid)
|
| + return X509_V_OK;
|
| +
|
| + /* Check key ids (if present) */
|
| + if(akid->keyid && issuer->skid &&
|
| + ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid) )
|
| + return X509_V_ERR_AKID_SKID_MISMATCH;
|
| + /* Check serial number */
|
| + if(akid->serial &&
|
| + ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
|
| + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
|
| + /* Check issuer name */
|
| + if(akid->issuer)
|
| + {
|
| + /* Ugh, for some peculiar reason AKID includes
|
| + * SEQUENCE OF GeneralName. So look for a DirName.
|
| + * There may be more than one but we only take any
|
| + * notice of the first.
|
| + */
|
| + GENERAL_NAMES *gens;
|
| + GENERAL_NAME *gen;
|
| + X509_NAME *nm = NULL;
|
| + int i;
|
| + gens = akid->issuer;
|
| + for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
|
| + {
|
| + gen = sk_GENERAL_NAME_value(gens, i);
|
| + if(gen->type == GEN_DIRNAME)
|
| + {
|
| + nm = gen->d.dirn;
|
| + break;
|
| + }
|
| + }
|
| + if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
|
| + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
|
| + }
|
| + return X509_V_OK;
|
| + }
|
| +
|
|
|