diff options
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 | |||