diff options
| author | markus <> | 2002-09-05 12:51:50 +0000 |
|---|---|---|
| committer | markus <> | 2002-09-05 12:51:50 +0000 |
| commit | 15b5d84f9da2ce4bfae8580e56e34a859f74ad71 (patch) | |
| tree | bf939e82d7fd73cc8a01cf6959002209972091bc /src/lib/libcrypto/x509v3/v3_purp.c | |
| parent | 027351f729b9e837200dae6e1520cda6577ab930 (diff) | |
| download | openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.gz openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.bz2 openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.zip | |
import openssl-0.9.7-beta1
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_purp.c')
| -rw-r--r-- | src/lib/libcrypto/x509v3/v3_purp.c | 271 |
1 files changed, 220 insertions, 51 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_purp.c b/src/lib/libcrypto/x509v3/v3_purp.c index b7494ebcd5..b739e4fd83 100644 --- a/src/lib/libcrypto/x509v3/v3_purp.c +++ b/src/lib/libcrypto/x509v3/v3_purp.c | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | /* v3_purp.c */ | 1 | /* v3_purp.c */ |
| 2 | /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL |
| 3 | * project 1999. | 3 | * project 2001. |
| 4 | */ | 4 | */ |
| 5 | /* ==================================================================== | 5 | /* ==================================================================== |
| 6 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | 6 | * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions |
| @@ -59,20 +59,24 @@ | |||
| 59 | #include <stdio.h> | 59 | #include <stdio.h> |
| 60 | #include "cryptlib.h" | 60 | #include "cryptlib.h" |
| 61 | #include <openssl/x509v3.h> | 61 | #include <openssl/x509v3.h> |
| 62 | 62 | #include <openssl/x509_vfy.h> | |
| 63 | 63 | ||
| 64 | static void x509v3_cache_extensions(X509 *x); | 64 | static void x509v3_cache_extensions(X509 *x); |
| 65 | 65 | ||
| 66 | static int ca_check(X509 *x); | 66 | static int ca_check(const X509 *x); |
| 67 | static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca); | 67 | static int check_ssl_ca(const X509 *x); |
| 68 | static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); | 68 | static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca); |
| 69 | static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); | 69 | static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca); |
| 70 | static int purpose_smime(X509 *x, int ca); | 70 | static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca); |
| 71 | static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca); | 71 | static int purpose_smime(const X509 *x, int ca); |
| 72 | static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca); | 72 | static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca); |
| 73 | static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca); | 73 | static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca); |
| 74 | 74 | static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca); | |
| 75 | static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b); | 75 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); |
| 76 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); | ||
| 77 | |||
| 78 | static int xp_cmp(const X509_PURPOSE * const *a, | ||
| 79 | const X509_PURPOSE * const *b); | ||
| 76 | static void xptable_free(X509_PURPOSE *p); | 80 | static void xptable_free(X509_PURPOSE *p); |
| 77 | 81 | ||
| 78 | static X509_PURPOSE xstandard[] = { | 82 | static X509_PURPOSE xstandard[] = { |
| @@ -81,7 +85,9 @@ static X509_PURPOSE xstandard[] = { | |||
| 81 | {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, | 85 | {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, |
| 82 | {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, "S/MIME signing", "smimesign", NULL}, | 86 | {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, "S/MIME signing", "smimesign", NULL}, |
| 83 | {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, | 87 | {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, |
| 84 | {X509_PURPOSE_CRL_SIGN, X509_TRUST_ANY, 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}, |
| 89 | {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL}, | ||
| 90 | {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL}, | ||
| 85 | }; | 91 | }; |
| 86 | 92 | ||
| 87 | #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) | 93 | #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) |
| @@ -90,15 +96,19 @@ IMPLEMENT_STACK_OF(X509_PURPOSE) | |||
| 90 | 96 | ||
| 91 | static STACK_OF(X509_PURPOSE) *xptable = NULL; | 97 | static STACK_OF(X509_PURPOSE) *xptable = NULL; |
| 92 | 98 | ||
| 93 | static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b) | 99 | static int xp_cmp(const X509_PURPOSE * const *a, |
| 100 | const X509_PURPOSE * const *b) | ||
| 94 | { | 101 | { |
| 95 | return (*a)->purpose - (*b)->purpose; | 102 | return (*a)->purpose - (*b)->purpose; |
| 96 | } | 103 | } |
| 97 | 104 | ||
| 105 | /* As much as I'd like to make X509_check_purpose use a "const" X509* | ||
| 106 | * I really can't because it does recalculate hashes and do other non-const | ||
| 107 | * things. */ | ||
| 98 | int X509_check_purpose(X509 *x, int id, int ca) | 108 | int X509_check_purpose(X509 *x, int id, int ca) |
| 99 | { | 109 | { |
| 100 | int idx; | 110 | int idx; |
| 101 | X509_PURPOSE *pt; | 111 | const X509_PURPOSE *pt; |
| 102 | if(!(x->ex_flags & EXFLAG_SET)) { | 112 | if(!(x->ex_flags & EXFLAG_SET)) { |
| 103 | CRYPTO_w_lock(CRYPTO_LOCK_X509); | 113 | CRYPTO_w_lock(CRYPTO_LOCK_X509); |
| 104 | x509v3_cache_extensions(x); | 114 | x509v3_cache_extensions(x); |
| @@ -111,6 +121,16 @@ int X509_check_purpose(X509 *x, int id, int ca) | |||
| 111 | return pt->check_purpose(pt, x, ca); | 121 | return pt->check_purpose(pt, x, ca); |
| 112 | } | 122 | } |
| 113 | 123 | ||
| 124 | int X509_PURPOSE_set(int *p, int purpose) | ||
| 125 | { | ||
| 126 | if(X509_PURPOSE_get_by_id(purpose) == -1) { | ||
| 127 | X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE); | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | *p = purpose; | ||
| 131 | return 1; | ||
| 132 | } | ||
| 133 | |||
| 114 | int X509_PURPOSE_get_count(void) | 134 | int X509_PURPOSE_get_count(void) |
| 115 | { | 135 | { |
| 116 | if(!xptable) return X509_PURPOSE_COUNT; | 136 | if(!xptable) return X509_PURPOSE_COUNT; |
| @@ -135,7 +155,6 @@ int X509_PURPOSE_get_by_sname(char *sname) | |||
| 135 | return -1; | 155 | return -1; |
| 136 | } | 156 | } |
| 137 | 157 | ||
| 138 | |||
| 139 | int X509_PURPOSE_get_by_id(int purpose) | 158 | int X509_PURPOSE_get_by_id(int purpose) |
| 140 | { | 159 | { |
| 141 | X509_PURPOSE tmp; | 160 | X509_PURPOSE tmp; |
| @@ -150,7 +169,7 @@ int X509_PURPOSE_get_by_id(int purpose) | |||
| 150 | } | 169 | } |
| 151 | 170 | ||
| 152 | int X509_PURPOSE_add(int id, int trust, int flags, | 171 | int X509_PURPOSE_add(int id, int trust, int flags, |
| 153 | int (*ck)(X509_PURPOSE *, X509 *, int), | 172 | int (*ck)(const X509_PURPOSE *, const X509 *, int), |
| 154 | char *name, char *sname, void *arg) | 173 | char *name, char *sname, void *arg) |
| 155 | { | 174 | { |
| 156 | int idx; | 175 | int idx; |
| @@ -163,17 +182,17 @@ int X509_PURPOSE_add(int id, int trust, int flags, | |||
| 163 | idx = X509_PURPOSE_get_by_id(id); | 182 | idx = X509_PURPOSE_get_by_id(id); |
| 164 | /* Need a new entry */ | 183 | /* Need a new entry */ |
| 165 | if(idx == -1) { | 184 | if(idx == -1) { |
| 166 | if(!(ptmp = Malloc(sizeof(X509_PURPOSE)))) { | 185 | if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { |
| 167 | X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); | 186 | X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); |
| 168 | return 0; | 187 | return 0; |
| 169 | } | 188 | } |
| 170 | ptmp->flags = X509_PURPOSE_DYNAMIC; | 189 | ptmp->flags = X509_PURPOSE_DYNAMIC; |
| 171 | } else ptmp = X509_PURPOSE_get0(idx); | 190 | } else ptmp = X509_PURPOSE_get0(idx); |
| 172 | 191 | ||
| 173 | /* Free existing name if dynamic */ | 192 | /* OPENSSL_free existing name if dynamic */ |
| 174 | if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { | 193 | if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { |
| 175 | Free(ptmp->name); | 194 | OPENSSL_free(ptmp->name); |
| 176 | Free(ptmp->sname); | 195 | OPENSSL_free(ptmp->sname); |
| 177 | } | 196 | } |
| 178 | /* dup supplied name */ | 197 | /* dup supplied name */ |
| 179 | ptmp->name = BUF_strdup(name); | 198 | ptmp->name = BUF_strdup(name); |
| @@ -212,10 +231,10 @@ static void xptable_free(X509_PURPOSE *p) | |||
| 212 | if (p->flags & X509_PURPOSE_DYNAMIC) | 231 | if (p->flags & X509_PURPOSE_DYNAMIC) |
| 213 | { | 232 | { |
| 214 | if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { | 233 | if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { |
| 215 | Free(p->name); | 234 | OPENSSL_free(p->name); |
| 216 | Free(p->sname); | 235 | OPENSSL_free(p->sname); |
| 217 | } | 236 | } |
| 218 | Free(p); | 237 | OPENSSL_free(p); |
| 219 | } | 238 | } |
| 220 | } | 239 | } |
| 221 | 240 | ||
| @@ -247,16 +266,57 @@ int X509_PURPOSE_get_trust(X509_PURPOSE *xp) | |||
| 247 | return xp->trust; | 266 | return xp->trust; |
| 248 | } | 267 | } |
| 249 | 268 | ||
| 250 | #ifndef NO_SHA | 269 | static int nid_cmp(int *a, int *b) |
| 270 | { | ||
| 271 | return *a - *b; | ||
| 272 | } | ||
| 273 | |||
| 274 | int X509_supported_extension(X509_EXTENSION *ex) | ||
| 275 | { | ||
| 276 | /* This table is a list of the NIDs of supported extensions: | ||
| 277 | * that is those which are used by the verify process. If | ||
| 278 | * an extension is critical and doesn't appear in this list | ||
| 279 | * then the verify process will normally reject the certificate. | ||
| 280 | * The list must be kept in numerical order because it will be | ||
| 281 | * searched using bsearch. | ||
| 282 | */ | ||
| 283 | |||
| 284 | static int supported_nids[] = { | ||
| 285 | NID_netscape_cert_type, /* 71 */ | ||
| 286 | NID_key_usage, /* 83 */ | ||
| 287 | NID_subject_alt_name, /* 85 */ | ||
| 288 | NID_basic_constraints, /* 87 */ | ||
| 289 | NID_ext_key_usage /* 126 */ | ||
| 290 | }; | ||
| 291 | |||
| 292 | int ex_nid; | ||
| 293 | |||
| 294 | ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); | ||
| 295 | |||
| 296 | if (ex_nid == NID_undef) | ||
| 297 | return 0; | ||
| 298 | |||
| 299 | if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids, | ||
| 300 | sizeof(supported_nids)/sizeof(int), sizeof(int), | ||
| 301 | (int (*)(const void *, const void *))nid_cmp)) | ||
| 302 | return 1; | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | |||
| 251 | static void x509v3_cache_extensions(X509 *x) | 307 | static void x509v3_cache_extensions(X509 *x) |
| 252 | { | 308 | { |
| 253 | BASIC_CONSTRAINTS *bs; | 309 | BASIC_CONSTRAINTS *bs; |
| 254 | ASN1_BIT_STRING *usage; | 310 | ASN1_BIT_STRING *usage; |
| 255 | ASN1_BIT_STRING *ns; | 311 | ASN1_BIT_STRING *ns; |
| 256 | STACK_OF(ASN1_OBJECT) *extusage; | 312 | EXTENDED_KEY_USAGE *extusage; |
| 313 | X509_EXTENSION *ex; | ||
| 314 | |||
| 257 | int i; | 315 | int i; |
| 258 | if(x->ex_flags & EXFLAG_SET) return; | 316 | if(x->ex_flags & EXFLAG_SET) return; |
| 317 | #ifndef OPENSSL_NO_SHA | ||
| 259 | X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); | 318 | X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); |
| 319 | #endif | ||
| 260 | /* Does subject name match issuer ? */ | 320 | /* Does subject name match issuer ? */ |
| 261 | if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) | 321 | if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) |
| 262 | x->ex_flags |= EXFLAG_SS; | 322 | x->ex_flags |= EXFLAG_SS; |
| @@ -309,6 +369,15 @@ static void x509v3_cache_extensions(X509 *x) | |||
| 309 | case NID_ms_sgc: | 369 | case NID_ms_sgc: |
| 310 | case NID_ns_sgc: | 370 | case NID_ns_sgc: |
| 311 | x->ex_xkusage |= XKU_SGC; | 371 | x->ex_xkusage |= XKU_SGC; |
| 372 | break; | ||
| 373 | |||
| 374 | case NID_OCSP_sign: | ||
| 375 | x->ex_xkusage |= XKU_OCSP_SIGN; | ||
| 376 | break; | ||
| 377 | |||
| 378 | case NID_time_stamp: | ||
| 379 | x->ex_xkusage |= XKU_TIMESTAMP; | ||
| 380 | break; | ||
| 312 | } | 381 | } |
| 313 | } | 382 | } |
| 314 | sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); | 383 | sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); |
| @@ -320,9 +389,21 @@ static void x509v3_cache_extensions(X509 *x) | |||
| 320 | x->ex_flags |= EXFLAG_NSCERT; | 389 | x->ex_flags |= EXFLAG_NSCERT; |
| 321 | ASN1_BIT_STRING_free(ns); | 390 | ASN1_BIT_STRING_free(ns); |
| 322 | } | 391 | } |
| 392 | x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); | ||
| 393 | x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); | ||
| 394 | for (i = 0; i < X509_get_ext_count(x); i++) | ||
| 395 | { | ||
| 396 | ex = X509_get_ext(x, i); | ||
| 397 | if (!X509_EXTENSION_get_critical(ex)) | ||
| 398 | continue; | ||
| 399 | if (!X509_supported_extension(ex)) | ||
| 400 | { | ||
| 401 | x->ex_flags |= EXFLAG_CRITICAL; | ||
| 402 | break; | ||
| 403 | } | ||
| 404 | } | ||
| 323 | x->ex_flags |= EXFLAG_SET; | 405 | x->ex_flags |= EXFLAG_SET; |
| 324 | } | 406 | } |
| 325 | #endif | ||
| 326 | 407 | ||
| 327 | /* CA checks common to all purposes | 408 | /* CA checks common to all purposes |
| 328 | * return codes: | 409 | * return codes: |
| @@ -340,7 +421,7 @@ static void x509v3_cache_extensions(X509 *x) | |||
| 340 | #define ns_reject(x, usage) \ | 421 | #define ns_reject(x, usage) \ |
| 341 | (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) | 422 | (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) |
| 342 | 423 | ||
| 343 | static int ca_check(X509 *x) | 424 | static int ca_check(const X509 *x) |
| 344 | { | 425 | { |
| 345 | /* keyUsage if present should allow cert signing */ | 426 | /* keyUsage if present should allow cert signing */ |
| 346 | if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0; | 427 | if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0; |
| @@ -350,26 +431,32 @@ static int ca_check(X509 *x) | |||
| 350 | else return 0; | 431 | else return 0; |
| 351 | } else { | 432 | } else { |
| 352 | if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3; | 433 | if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3; |
| 434 | /* If key usage present it must have certSign so tolerate it */ | ||
| 435 | else if (x->ex_flags & EXFLAG_KUSAGE) return 3; | ||
| 353 | else return 2; | 436 | else return 2; |
| 354 | } | 437 | } |
| 355 | } | 438 | } |
| 356 | 439 | ||
| 440 | /* Check SSL CA: common checks for SSL client and server */ | ||
| 441 | static int check_ssl_ca(const X509 *x) | ||
| 442 | { | ||
| 443 | int ca_ret; | ||
| 444 | ca_ret = ca_check(x); | ||
| 445 | if(!ca_ret) return 0; | ||
| 446 | /* check nsCertType if present */ | ||
| 447 | if(x->ex_flags & EXFLAG_NSCERT) { | ||
| 448 | if(x->ex_nscert & NS_SSL_CA) return ca_ret; | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | if(ca_ret != 2) return ca_ret; | ||
| 452 | else return 0; | ||
| 453 | } | ||
| 357 | 454 | ||
| 358 | static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca) | 455 | |
| 456 | static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca) | ||
| 359 | { | 457 | { |
| 360 | if(xku_reject(x,XKU_SSL_CLIENT)) return 0; | 458 | if(xku_reject(x,XKU_SSL_CLIENT)) return 0; |
| 361 | if(ca) { | 459 | if(ca) return check_ssl_ca(x); |
| 362 | int ca_ret; | ||
| 363 | ca_ret = ca_check(x); | ||
| 364 | if(!ca_ret) return 0; | ||
| 365 | /* check nsCertType if present */ | ||
| 366 | if(x->ex_flags & EXFLAG_NSCERT) { | ||
| 367 | if(x->ex_nscert & NS_SSL_CA) return ca_ret; | ||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | if(ca_ret != 2) return ca_ret; | ||
| 371 | else return 0; | ||
| 372 | } | ||
| 373 | /* We need to do digital signatures with it */ | 460 | /* We need to do digital signatures with it */ |
| 374 | if(ku_reject(x,KU_DIGITAL_SIGNATURE)) return 0; | 461 | if(ku_reject(x,KU_DIGITAL_SIGNATURE)) return 0; |
| 375 | /* nsCertType if present should allow SSL client use */ | 462 | /* nsCertType if present should allow SSL client use */ |
| @@ -377,11 +464,10 @@ static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca) | |||
| 377 | return 1; | 464 | return 1; |
| 378 | } | 465 | } |
| 379 | 466 | ||
| 380 | static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) | 467 | static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca) |
| 381 | { | 468 | { |
| 382 | if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0; | 469 | if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0; |
| 383 | /* Otherwise same as SSL client for a CA */ | 470 | if(ca) return check_ssl_ca(x); |
| 384 | if(ca) return check_purpose_ssl_client(xp, x, 1); | ||
| 385 | 471 | ||
| 386 | if(ns_reject(x, NS_SSL_SERVER)) return 0; | 472 | if(ns_reject(x, NS_SSL_SERVER)) return 0; |
| 387 | /* Now as for keyUsage: we'll at least need to sign OR encipher */ | 473 | /* Now as for keyUsage: we'll at least need to sign OR encipher */ |
| @@ -391,7 +477,7 @@ static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) | |||
| 391 | 477 | ||
| 392 | } | 478 | } |
| 393 | 479 | ||
| 394 | static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) | 480 | static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca) |
| 395 | { | 481 | { |
| 396 | int ret; | 482 | int ret; |
| 397 | ret = check_purpose_ssl_server(xp, x, ca); | 483 | ret = check_purpose_ssl_server(xp, x, ca); |
| @@ -402,7 +488,7 @@ static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) | |||
| 402 | } | 488 | } |
| 403 | 489 | ||
| 404 | /* common S/MIME checks */ | 490 | /* common S/MIME checks */ |
| 405 | static int purpose_smime(X509 *x, int ca) | 491 | static int purpose_smime(const X509 *x, int ca) |
| 406 | { | 492 | { |
| 407 | if(xku_reject(x,XKU_SMIME)) return 0; | 493 | if(xku_reject(x,XKU_SMIME)) return 0; |
| 408 | if(ca) { | 494 | if(ca) { |
| @@ -426,16 +512,16 @@ static int purpose_smime(X509 *x, int ca) | |||
| 426 | return 1; | 512 | return 1; |
| 427 | } | 513 | } |
| 428 | 514 | ||
| 429 | static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca) | 515 | static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca) |
| 430 | { | 516 | { |
| 431 | int ret; | 517 | int ret; |
| 432 | ret = purpose_smime(x, ca); | 518 | ret = purpose_smime(x, ca); |
| 433 | if(!ret || ca) return ret; | 519 | if(!ret || ca) return ret; |
| 434 | if(ku_reject(x, KU_DIGITAL_SIGNATURE)) return 0; | 520 | if(ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION)) return 0; |
| 435 | return ret; | 521 | return ret; |
| 436 | } | 522 | } |
| 437 | 523 | ||
| 438 | static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca) | 524 | static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca) |
| 439 | { | 525 | { |
| 440 | int ret; | 526 | int ret; |
| 441 | ret = purpose_smime(x, ca); | 527 | ret = purpose_smime(x, ca); |
| @@ -444,7 +530,7 @@ static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca) | |||
| 444 | return ret; | 530 | return ret; |
| 445 | } | 531 | } |
| 446 | 532 | ||
| 447 | static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca) | 533 | static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca) |
| 448 | { | 534 | { |
| 449 | if(ca) { | 535 | if(ca) { |
| 450 | int ca_ret; | 536 | int ca_ret; |
| @@ -454,3 +540,86 @@ static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca) | |||
| 454 | if(ku_reject(x, KU_CRL_SIGN)) return 0; | 540 | if(ku_reject(x, KU_CRL_SIGN)) return 0; |
| 455 | return 1; | 541 | return 1; |
| 456 | } | 542 | } |
| 543 | |||
| 544 | /* OCSP helper: this is *not* a full OCSP check. It just checks that | ||
| 545 | * each CA is valid. Additional checks must be made on the chain. | ||
| 546 | */ | ||
| 547 | |||
| 548 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) | ||
| 549 | { | ||
| 550 | /* Must be a valid CA */ | ||
| 551 | if(ca) { | ||
| 552 | int ca_ret; | ||
| 553 | ca_ret = ca_check(x); | ||
| 554 | if(ca_ret != 2) return ca_ret; | ||
| 555 | if(x->ex_flags & EXFLAG_NSCERT) { | ||
| 556 | if(x->ex_nscert & NS_ANY_CA) return ca_ret; | ||
| 557 | return 0; | ||
| 558 | } | ||
| 559 | return 0; | ||
| 560 | } | ||
| 561 | /* leaf certificate is checked in OCSP_verify() */ | ||
| 562 | return 1; | ||
| 563 | } | ||
| 564 | |||
| 565 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) | ||
| 566 | { | ||
| 567 | return 1; | ||
| 568 | } | ||
| 569 | |||
| 570 | /* Various checks to see if one certificate issued the second. | ||
| 571 | * This can be used to prune a set of possible issuer certificates | ||
| 572 | * which have been looked up using some simple method such as by | ||
| 573 | * subject name. | ||
| 574 | * These are: | ||
| 575 | * 1. Check issuer_name(subject) == subject_name(issuer) | ||
| 576 | * 2. If akid(subject) exists check it matches issuer | ||
| 577 | * 3. If key_usage(issuer) exists check it supports certificate signing | ||
| 578 | * returns 0 for OK, positive for reason for mismatch, reasons match | ||
| 579 | * codes for X509_verify_cert() | ||
| 580 | */ | ||
| 581 | |||
| 582 | int X509_check_issued(X509 *issuer, X509 *subject) | ||
| 583 | { | ||
| 584 | if(X509_NAME_cmp(X509_get_subject_name(issuer), | ||
| 585 | X509_get_issuer_name(subject))) | ||
| 586 | return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; | ||
| 587 | x509v3_cache_extensions(issuer); | ||
| 588 | x509v3_cache_extensions(subject); | ||
| 589 | if(subject->akid) { | ||
| 590 | /* Check key ids (if present) */ | ||
| 591 | if(subject->akid->keyid && issuer->skid && | ||
| 592 | ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid) ) | ||
| 593 | return X509_V_ERR_AKID_SKID_MISMATCH; | ||
| 594 | /* Check serial number */ | ||
| 595 | if(subject->akid->serial && | ||
| 596 | ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), | ||
| 597 | subject->akid->serial)) | ||
| 598 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; | ||
| 599 | /* Check issuer name */ | ||
| 600 | if(subject->akid->issuer) { | ||
| 601 | /* Ugh, for some peculiar reason AKID includes | ||
| 602 | * SEQUENCE OF GeneralName. So look for a DirName. | ||
| 603 | * There may be more than one but we only take any | ||
| 604 | * notice of the first. | ||
| 605 | */ | ||
| 606 | GENERAL_NAMES *gens; | ||
| 607 | GENERAL_NAME *gen; | ||
| 608 | X509_NAME *nm = NULL; | ||
| 609 | int i; | ||
| 610 | gens = subject->akid->issuer; | ||
| 611 | for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) { | ||
| 612 | gen = sk_GENERAL_NAME_value(gens, i); | ||
| 613 | if(gen->type == GEN_DIRNAME) { | ||
| 614 | nm = gen->d.dirn; | ||
| 615 | break; | ||
| 616 | } | ||
| 617 | } | ||
| 618 | if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) | ||
| 619 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | if(ku_reject(issuer, KU_KEY_CERT_SIGN)) return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; | ||
| 623 | return X509_V_OK; | ||
| 624 | } | ||
| 625 | |||
