summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509v3/v3_purp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_purp.c')
-rw-r--r--src/lib/libcrypto/x509v3/v3_purp.c162
1 files changed, 116 insertions, 46 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_purp.c b/src/lib/libcrypto/x509v3/v3_purp.c
index 5594a1d64f..867699b26f 100644
--- a/src/lib/libcrypto/x509v3/v3_purp.c
+++ b/src/lib/libcrypto/x509v3/v3_purp.c
@@ -59,21 +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#include <openssl/x509_vfy.h>
62 63
63 64
64static void x509v3_cache_extensions(X509 *x); 65static void x509v3_cache_extensions(X509 *x);
65 66
66static int ca_check(X509 *x); 67static int ca_check(const X509 *x);
67static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca); 68static int check_ssl_ca(const X509 *x);
68static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); 69static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca);
69static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); 70static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
70static int purpose_smime(X509 *x, int ca); 71static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
71static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca); 72static int purpose_smime(const X509 *x, int ca);
72static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca); 73static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
73static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca); 74static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca);
74static int no_check(X509_PURPOSE *xp, X509 *x, int ca); 75static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
75 76static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
76static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b); 77
78static int xp_cmp(const X509_PURPOSE * const *a,
79 const X509_PURPOSE * const *b);
77static void xptable_free(X509_PURPOSE *p); 80static void xptable_free(X509_PURPOSE *p);
78 81
79static X509_PURPOSE xstandard[] = { 82static X509_PURPOSE xstandard[] = {
@@ -92,15 +95,19 @@ IMPLEMENT_STACK_OF(X509_PURPOSE)
92 95
93static STACK_OF(X509_PURPOSE) *xptable = NULL; 96static STACK_OF(X509_PURPOSE) *xptable = NULL;
94 97
95static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b) 98static int xp_cmp(const X509_PURPOSE * const *a,
99 const X509_PURPOSE * const *b)
96{ 100{
97 return (*a)->purpose - (*b)->purpose; 101 return (*a)->purpose - (*b)->purpose;
98} 102}
99 103
104/* As much as I'd like to make X509_check_purpose use a "const" X509*
105 * I really can't because it does recalculate hashes and do other non-const
106 * things. */
100int X509_check_purpose(X509 *x, int id, int ca) 107int X509_check_purpose(X509 *x, int id, int ca)
101{ 108{
102 int idx; 109 int idx;
103 X509_PURPOSE *pt; 110 const X509_PURPOSE *pt;
104 if(!(x->ex_flags & EXFLAG_SET)) { 111 if(!(x->ex_flags & EXFLAG_SET)) {
105 CRYPTO_w_lock(CRYPTO_LOCK_X509); 112 CRYPTO_w_lock(CRYPTO_LOCK_X509);
106 x509v3_cache_extensions(x); 113 x509v3_cache_extensions(x);
@@ -152,7 +159,7 @@ int X509_PURPOSE_get_by_id(int purpose)
152} 159}
153 160
154int X509_PURPOSE_add(int id, int trust, int flags, 161int X509_PURPOSE_add(int id, int trust, int flags,
155 int (*ck)(X509_PURPOSE *, X509 *, int), 162 int (*ck)(const X509_PURPOSE *, const X509 *, int),
156 char *name, char *sname, void *arg) 163 char *name, char *sname, void *arg)
157{ 164{
158 int idx; 165 int idx;
@@ -165,17 +172,17 @@ int X509_PURPOSE_add(int id, int trust, int flags,
165 idx = X509_PURPOSE_get_by_id(id); 172 idx = X509_PURPOSE_get_by_id(id);
166 /* Need a new entry */ 173 /* Need a new entry */
167 if(idx == -1) { 174 if(idx == -1) {
168 if(!(ptmp = Malloc(sizeof(X509_PURPOSE)))) { 175 if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
169 X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); 176 X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE);
170 return 0; 177 return 0;
171 } 178 }
172 ptmp->flags = X509_PURPOSE_DYNAMIC; 179 ptmp->flags = X509_PURPOSE_DYNAMIC;
173 } else ptmp = X509_PURPOSE_get0(idx); 180 } else ptmp = X509_PURPOSE_get0(idx);
174 181
175 /* Free existing name if dynamic */ 182 /* OPENSSL_free existing name if dynamic */
176 if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { 183 if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
177 Free(ptmp->name); 184 OPENSSL_free(ptmp->name);
178 Free(ptmp->sname); 185 OPENSSL_free(ptmp->sname);
179 } 186 }
180 /* dup supplied name */ 187 /* dup supplied name */
181 ptmp->name = BUF_strdup(name); 188 ptmp->name = BUF_strdup(name);
@@ -214,10 +221,10 @@ static void xptable_free(X509_PURPOSE *p)
214 if (p->flags & X509_PURPOSE_DYNAMIC) 221 if (p->flags & X509_PURPOSE_DYNAMIC)
215 { 222 {
216 if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { 223 if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
217 Free(p->name); 224 OPENSSL_free(p->name);
218 Free(p->sname); 225 OPENSSL_free(p->sname);
219 } 226 }
220 Free(p); 227 OPENSSL_free(p);
221 } 228 }
222 } 229 }
223 230
@@ -249,16 +256,18 @@ int X509_PURPOSE_get_trust(X509_PURPOSE *xp)
249 return xp->trust; 256 return xp->trust;
250} 257}
251 258
252#ifndef NO_SHA
253static void x509v3_cache_extensions(X509 *x) 259static void x509v3_cache_extensions(X509 *x)
254{ 260{
255 BASIC_CONSTRAINTS *bs; 261 BASIC_CONSTRAINTS *bs;
256 ASN1_BIT_STRING *usage; 262 ASN1_BIT_STRING *usage;
257 ASN1_BIT_STRING *ns; 263 ASN1_BIT_STRING *ns;
258 STACK_OF(ASN1_OBJECT) *extusage; 264 STACK_OF(ASN1_OBJECT) *extusage;
265
259 int i; 266 int i;
260 if(x->ex_flags & EXFLAG_SET) return; 267 if(x->ex_flags & EXFLAG_SET) return;
268#ifndef NO_SHA
261 X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); 269 X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
270#endif
262 /* Does subject name match issuer ? */ 271 /* Does subject name match issuer ? */
263 if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) 272 if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
264 x->ex_flags |= EXFLAG_SS; 273 x->ex_flags |= EXFLAG_SS;
@@ -322,9 +331,10 @@ static void x509v3_cache_extensions(X509 *x)
322 x->ex_flags |= EXFLAG_NSCERT; 331 x->ex_flags |= EXFLAG_NSCERT;
323 ASN1_BIT_STRING_free(ns); 332 ASN1_BIT_STRING_free(ns);
324 } 333 }
334 x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
335 x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
325 x->ex_flags |= EXFLAG_SET; 336 x->ex_flags |= EXFLAG_SET;
326} 337}
327#endif
328 338
329/* CA checks common to all purposes 339/* CA checks common to all purposes
330 * return codes: 340 * return codes:
@@ -342,7 +352,7 @@ static void x509v3_cache_extensions(X509 *x)
342#define ns_reject(x, usage) \ 352#define ns_reject(x, usage) \
343 (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) 353 (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
344 354
345static int ca_check(X509 *x) 355static int ca_check(const X509 *x)
346{ 356{
347 /* keyUsage if present should allow cert signing */ 357 /* keyUsage if present should allow cert signing */
348 if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0; 358 if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0;
@@ -356,22 +366,26 @@ static int ca_check(X509 *x)
356 } 366 }
357} 367}
358 368
369/* Check SSL CA: common checks for SSL client and server */
370static int check_ssl_ca(const X509 *x)
371{
372 int ca_ret;
373 ca_ret = ca_check(x);
374 if(!ca_ret) return 0;
375 /* check nsCertType if present */
376 if(x->ex_flags & EXFLAG_NSCERT) {
377 if(x->ex_nscert & NS_SSL_CA) return ca_ret;
378 return 0;
379 }
380 if(ca_ret != 2) return ca_ret;
381 else return 0;
382}
383
359 384
360static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca) 385static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca)
361{ 386{
362 if(xku_reject(x,XKU_SSL_CLIENT)) return 0; 387 if(xku_reject(x,XKU_SSL_CLIENT)) return 0;
363 if(ca) { 388 if(ca) return check_ssl_ca(x);
364 int ca_ret;
365 ca_ret = ca_check(x);
366 if(!ca_ret) return 0;
367 /* check nsCertType if present */
368 if(x->ex_flags & EXFLAG_NSCERT) {
369 if(x->ex_nscert & NS_SSL_CA) return ca_ret;
370 return 0;
371 }
372 if(ca_ret != 2) return ca_ret;
373 else return 0;
374 }
375 /* We need to do digital signatures with it */ 389 /* We need to do digital signatures with it */
376 if(ku_reject(x,KU_DIGITAL_SIGNATURE)) return 0; 390 if(ku_reject(x,KU_DIGITAL_SIGNATURE)) return 0;
377 /* nsCertType if present should allow SSL client use */ 391 /* nsCertType if present should allow SSL client use */
@@ -379,11 +393,10 @@ static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca)
379 return 1; 393 return 1;
380} 394}
381 395
382static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) 396static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
383{ 397{
384 if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0; 398 if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0;
385 /* Otherwise same as SSL client for a CA */ 399 if(ca) return check_ssl_ca(x);
386 if(ca) return check_purpose_ssl_client(xp, x, 1);
387 400
388 if(ns_reject(x, NS_SSL_SERVER)) return 0; 401 if(ns_reject(x, NS_SSL_SERVER)) return 0;
389 /* Now as for keyUsage: we'll at least need to sign OR encipher */ 402 /* Now as for keyUsage: we'll at least need to sign OR encipher */
@@ -393,7 +406,7 @@ static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca)
393 406
394} 407}
395 408
396static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) 409static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
397{ 410{
398 int ret; 411 int ret;
399 ret = check_purpose_ssl_server(xp, x, ca); 412 ret = check_purpose_ssl_server(xp, x, ca);
@@ -404,7 +417,7 @@ static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca)
404} 417}
405 418
406/* common S/MIME checks */ 419/* common S/MIME checks */
407static int purpose_smime(X509 *x, int ca) 420static int purpose_smime(const X509 *x, int ca)
408{ 421{
409 if(xku_reject(x,XKU_SMIME)) return 0; 422 if(xku_reject(x,XKU_SMIME)) return 0;
410 if(ca) { 423 if(ca) {
@@ -428,7 +441,7 @@ static int purpose_smime(X509 *x, int ca)
428 return 1; 441 return 1;
429} 442}
430 443
431static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca) 444static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
432{ 445{
433 int ret; 446 int ret;
434 ret = purpose_smime(x, ca); 447 ret = purpose_smime(x, ca);
@@ -437,7 +450,7 @@ static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca)
437 return ret; 450 return ret;
438} 451}
439 452
440static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca) 453static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca)
441{ 454{
442 int ret; 455 int ret;
443 ret = purpose_smime(x, ca); 456 ret = purpose_smime(x, ca);
@@ -446,7 +459,7 @@ static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca)
446 return ret; 459 return ret;
447} 460}
448 461
449static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca) 462static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
450{ 463{
451 if(ca) { 464 if(ca) {
452 int ca_ret; 465 int ca_ret;
@@ -457,7 +470,64 @@ static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca)
457 return 1; 470 return 1;
458} 471}
459 472
460static int no_check(X509_PURPOSE *xp, X509 *x, int ca) 473static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
461{ 474{
462 return 1; 475 return 1;
463} 476}
477
478/* Various checks to see if one certificate issued the second.
479 * This can be used to prune a set of possible issuer certificates
480 * which have been looked up using some simple method such as by
481 * subject name.
482 * These are:
483 * 1. Check issuer_name(subject) == subject_name(issuer)
484 * 2. If akid(subject) exists check it matches issuer
485 * 3. If key_usage(issuer) exists check it supports certificate signing
486 * returns 0 for OK, positive for reason for mismatch, reasons match
487 * codes for X509_verify_cert()
488 */
489
490int X509_check_issued(X509 *issuer, X509 *subject)
491{
492 if(X509_NAME_cmp(X509_get_subject_name(issuer),
493 X509_get_issuer_name(subject)))
494 return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
495 x509v3_cache_extensions(issuer);
496 x509v3_cache_extensions(subject);
497 if(subject->akid) {
498 /* Check key ids (if present) */
499 if(subject->akid->keyid && issuer->skid &&
500 ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid) )
501 return X509_V_ERR_AKID_SKID_MISMATCH;
502 /* Check serial number */
503 if(subject->akid->serial &&
504 ASN1_INTEGER_cmp(X509_get_serialNumber(issuer),
505 subject->akid->serial))
506 return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
507 /* Check issuer name */
508 if(subject->akid->issuer) {
509 /* Ugh, for some peculiar reason AKID includes
510 * SEQUENCE OF GeneralName. So look for a DirName.
511 * There may be more than one but we only take any
512 * notice of the first.
513 */
514 STACK_OF(GENERAL_NAME) *gens;
515 GENERAL_NAME *gen;
516 X509_NAME *nm = NULL;
517 int i;
518 gens = subject->akid->issuer;
519 for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
520 gen = sk_GENERAL_NAME_value(gens, i);
521 if(gen->type == GEN_DIRNAME) {
522 nm = gen->d.dirn;
523 break;
524 }
525 }
526 if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
527 return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
528 }
529 }
530 if(ku_reject(issuer, KU_KEY_CERT_SIGN)) return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
531 return X509_V_OK;
532}
533