PathValidator::_prepareNameConstraints()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.9666
c 0
b 0
f 0
nc 2
cc 2
nop 2
crap 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace X509\CertificationPath\PathValidation;
6
7
use Sop\CryptoBridge\Crypto;
8
use X509\Certificate\Certificate;
9
use X509\Certificate\TBSCertificate;
10
use X509\Certificate\Extension\CertificatePolicy\PolicyInformation;
11
use X509\CertificationPath\Exception\PathValidationException;
12
13
/**
14
 * Implements certification path validation.
15
 *
16
 * @link https://tools.ietf.org/html/rfc5280#section-6
17
 */
18
class PathValidator
19
{
20
    /**
21
     * Crypto engine.
22
     *
23
     * @var Crypto $_crypto
24
     */
25
    protected $_crypto;
26
    
27
    /**
28
     * Path validation configuration.
29
     *
30
     * @var PathValidationConfig $_config
31
     */
32
    protected $_config;
33
    
34
    /**
35
     * Certification path.
36
     *
37
     * @var Certificate[] $_certificates
38
     */
39
    protected $_certificates;
40
    
41
    /**
42
     * Certification path trust anchor.
43
     *
44
     * @var Certificate $_trustAnchor
45
     */
46
    protected $_trustAnchor;
47
    
48
    /**
49
     * Constructor.
50
     *
51
     * @param Crypto $crypto Crypto engine
52
     * @param PathValidationConfig $config Validation config
53
     * @param Certificate ...$certificates Certificates from the trust anchor to
54
     *        the end-entity certificate
55
     */
56 46
    public function __construct(Crypto $crypto, PathValidationConfig $config,
57
        Certificate ...$certificates)
58
    {
59 46
        if (!count($certificates)) {
60 1
            throw new \LogicException("No certificates.");
61
        }
62 45
        $this->_crypto = $crypto;
63 45
        $this->_config = $config;
64 45
        $this->_certificates = $certificates;
65
        // if trust anchor is explicitly given in configuration
66 45
        if ($config->hasTrustAnchor()) {
67 1
            $this->_trustAnchor = $config->trustAnchor();
68
        } else {
69 44
            $this->_trustAnchor = $certificates[0];
70
        }
71 45
    }
72
    
73
    /**
74
     * Validate certification path.
75
     *
76
     * @throws PathValidationException
77
     * @return PathValidationResult
78
     */
79 45
    public function validate(): PathValidationResult
80
    {
81 45
        $n = count($this->_certificates);
82 45
        $state = ValidatorState::initialize($this->_config, $this->_trustAnchor,
83 45
            $n);
84 45
        for ($i = 0; $i < $n; ++$i) {
85 44
            $state = $state->withIndex($i + 1);
86 44
            $cert = $this->_certificates[$i];
87
            // process certificate (section 6.1.3.)
88 44
            $state = $this->_processCertificate($state, $cert);
89 43
            if (!$state->isFinal()) {
90
                // prepare next certificate (section 6.1.4.)
91 43
                $state = $this->_prepareNext($state, $cert);
92
            }
93
        }
94 31
        if (!isset($cert)) {
95 1
            throw new \LogicException("No certificates.");
96
        }
97
        // wrap-up (section 6.1.5.)
98 30
        $state = $this->_wrapUp($state, $cert);
99
        // return outputs
100 28
        return $state->getResult($this->_certificates);
101
    }
102
    
103
    /**
104
     * Apply basic certificate processing according to RFC 5280 section 6.1.3.
105
     *
106
     * @link https://tools.ietf.org/html/rfc5280#section-6.1.3
107
     * @param ValidatorState $state
108
     * @param Certificate $cert
109
     * @throws PathValidationException
110
     * @return ValidatorState
111
     */
112 44
    private function _processCertificate(ValidatorState $state, Certificate $cert): ValidatorState
113
    {
114
        // (a.1) verify signature
115 44
        $this->_verifySignature($state, $cert);
116
        // (a.2) check validity period
117 44
        $this->_checkValidity($cert);
118
        // (a.3) check that certificate is not revoked
119 43
        $this->_checkRevocation($cert);
0 ignored issues
show
Unused Code introduced by
The call to the method X509\CertificationPath\P...tor::_checkRevocation() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
120
        // (a.4) check issuer
121 43
        $this->_checkIssuer($state, $cert);
122
        // (b)(c) if certificate is self-issued and it is not
123
        // the final certificate in the path, skip this step
124 43
        if (!($cert->isSelfIssued() && !$state->isFinal())) {
125
            // (b) check permitted subtrees
126 35
            $this->_checkPermittedSubtrees($state, $cert);
0 ignored issues
show
Unused Code introduced by
The call to the method X509\CertificationPath\P...heckPermittedSubtrees() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
127
            // (c) check excluded subtrees
128 35
            $this->_checkExcludedSubtrees($state, $cert);
0 ignored issues
show
Unused Code introduced by
The call to the method X509\CertificationPath\P...checkExcludedSubtrees() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
129
        }
130 43
        $extensions = $cert->tbsCertificate()->extensions();
131 43
        if ($extensions->hasCertificatePolicies()) {
132
            // (d) process policy information
133 26
            if ($state->hasValidPolicyTree()) {
134 14
                $state = $state->validPolicyTree()->processPolicies($state,
135 26
                    $cert);
136
            }
137
        } else {
138
            // (e) certificate policies extension not present,
139
            // set the valid_policy_tree to NULL
140 31
            $state = $state->withoutValidPolicyTree();
141
        }
142
        // (f) check that explicit_policy > 0 or valid_policy_tree is set
143 43
        if (!($state->explicitPolicy() > 0 || $state->hasValidPolicyTree())) {
144 3
            throw new PathValidationException("No valid policies.");
145
        }
146 43
        return $state;
147
    }
148
    
149
    /**
150
     * Apply preparation for the certificate i+1 according to rfc5280 section
151
     * 6.1.4.
152
     *
153
     * @link https://tools.ietf.org/html/rfc5280#section-6.1.4
154
     * @param ValidatorState $state
155
     * @param Certificate $cert
156
     * @return ValidatorState
157
     */
158 43
    private function _prepareNext(ValidatorState $state, Certificate $cert): ValidatorState
159
    {
160
        // (a)(b) if policy mappings extension is present
161 43
        $state = $this->_preparePolicyMappings($state, $cert);
162
        // (c) assign working_issuer_name
163 42
        $state = $state->withWorkingIssuerName(
164 42
            $cert->tbsCertificate()
165 42
                ->subject());
166
        // (d)(e)(f)
167 42
        $state = $this->_setPublicKeyState($state, $cert);
168
        // (g) if name constraints extension is present
169 42
        $state = $this->_prepareNameConstraints($state, $cert);
170
        // (h) if certificate is not self-issued
171 42
        if (!$cert->isSelfIssued()) {
172 21
            $state = $this->_prepareNonSelfIssued($state);
173
        }
174
        // (i) if policy constraints extension is present
175 42
        $state = $this->_preparePolicyConstraints($state, $cert);
176
        // (j) if inhibit any policy extension is present
177 42
        $state = $this->_prepareInhibitAnyPolicy($state, $cert);
178
        // (k) check basic constraints
179 42
        $this->_processBasicContraints($cert);
180
        // (l) verify max_path_length
181 40
        $state = $this->_verifyMaxPathLength($state, $cert);
182
        // (m) check pathLenContraint
183 40
        $state = $this->_processPathLengthContraint($state, $cert);
184
        // (n) check key usage
185 40
        $this->_checkKeyUsage($cert);
186
        // (o) process relevant extensions
187 39
        $state = $this->_processExtensions($state, $cert);
188 39
        return $state;
189
    }
190
    
191
    /**
192
     * Apply wrap-up procedure according to RFC 5280 section 6.1.5.
193
     *
194
     * @link https://tools.ietf.org/html/rfc5280#section-6.1.5
195
     * @param ValidatorState $state
196
     * @param Certificate $cert
197
     * @throws PathValidationException
198
     * @return ValidatorState
199
     */
200 30
    private function _wrapUp(ValidatorState $state, Certificate $cert): ValidatorState
201
    {
202 30
        $tbs_cert = $cert->tbsCertificate();
203 30
        $extensions = $tbs_cert->extensions();
204
        // (a)
205 30
        if ($state->explicitPolicy() > 0) {
206 26
            $state = $state->withExplicitPolicy($state->explicitPolicy() - 1);
207
        }
208
        // (b)
209 30
        if ($extensions->hasPolicyConstraints()) {
210 13
            $ext = $extensions->policyConstraints();
211 13
            if ($ext->hasRequireExplicitPolicy() &&
212 13
                 $ext->requireExplicitPolicy() == 0) {
213 1
                $state = $state->withExplicitPolicy(0);
214
            }
215
        }
216
        // (c)(d)(e)
217 30
        $state = $this->_setPublicKeyState($state, $cert);
218
        // (f) process relevant extensions
219 30
        $state = $this->_processExtensions($state, $cert);
220
        // (g) intersection of valid_policy_tree and the initial-policy-set
221 30
        $state = $this->_calculatePolicyIntersection($state);
222
        // check that explicit_policy > 0 or valid_policy_tree is set
223 30
        if (!($state->explicitPolicy() > 0 || $state->hasValidPolicyTree())) {
224 2
            throw new PathValidationException("No valid policies.");
225
        }
226
        // path validation succeeded
227 28
        return $state;
228
    }
229
    
230
    /**
231
     * Update working_public_key, working_public_key_parameters and
232
     * working_public_key_algorithm state variables from certificate.
233
     *
234
     * @param ValidatorState $state
235
     * @param Certificate $cert
236
     * @return ValidatorState
237
     */
238 42
    private function _setPublicKeyState(ValidatorState $state, Certificate $cert): ValidatorState
239
    {
240 42
        $pk_info = $cert->tbsCertificate()->subjectPublicKeyInfo();
241
        // assign working_public_key
242 42
        $state = $state->withWorkingPublicKey($pk_info);
243
        // assign working_public_key_parameters
244 42
        $params = ValidatorState::getAlgorithmParameters(
245 42
            $pk_info->algorithmIdentifier());
246 42
        if (null !== $params) {
247 42
            $state = $state->withWorkingPublicKeyParameters($params);
248
        } else {
249
            // if algorithms differ, set parameters to null
250 1
            if ($pk_info->algorithmIdentifier()->oid() !==
251 1
                 $state->workingPublicKeyAlgorithm()->oid()) {
252 1
                $state = $state->withWorkingPublicKeyParameters(null);
253
            }
254
        }
255
        // assign working_public_key_algorithm
256 42
        $state = $state->withWorkingPublicKeyAlgorithm(
257 42
            $pk_info->algorithmIdentifier());
258 42
        return $state;
259
    }
260
    
261
    /**
262
     * Verify certificate signature.
263
     *
264
     * @param ValidatorState $state
265
     * @param Certificate $cert
266
     * @throws PathValidationException
267
     */
268 44
    private function _verifySignature(ValidatorState $state, Certificate $cert)
269
    {
270
        try {
271 44
            $valid = $cert->verify($state->workingPublicKey(), $this->_crypto);
272 1
        } catch (\RuntimeException $e) {
273 1
            throw new PathValidationException(
274 1
                "Failed to verify signature: " . $e->getMessage(), 0, $e);
275
        }
276 44
        if (!$valid) {
277 2
            throw new PathValidationException(
278 2
                "Certificate signature doesn't match.");
279
        }
280 44
    }
281
    
282
    /**
283
     * Check certificate validity.
284
     *
285
     * @param Certificate $cert
286
     * @throws PathValidationException
287
     */
288 44
    private function _checkValidity(Certificate $cert)
289
    {
290 44
        $refdt = $this->_config->dateTime();
291 44
        $validity = $cert->tbsCertificate()->validity();
292 44
        if ($validity->notBefore()
293 44
            ->dateTime()
294 44
            ->diff($refdt)->invert) {
295 1
            throw new PathValidationException(
296 1
                "Certificate validity period has not started.");
297
        }
298 43
        if ($refdt->diff($validity->notAfter()
299 43
            ->dateTime())->invert) {
300 1
            throw new PathValidationException("Certificate has expired.");
301
        }
302 43
    }
303
    
304
    /**
305
     * Check certificate revocation.
306
     *
307
     * @param Certificate $cert
308
     */
309 43
    private function _checkRevocation(Certificate $cert)
0 ignored issues
show
Unused Code introduced by
The parameter $cert is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
310
    {
311
        // @todo Implement CRL handling
312 43
    }
313
    
314
    /**
315
     * Check certificate issuer.
316
     *
317
     * @param ValidatorState $state
318
     * @param Certificate $cert
319
     * @throws PathValidationException
320
     */
321 43
    private function _checkIssuer(ValidatorState $state, Certificate $cert)
322
    {
323 43
        if (!$cert->tbsCertificate()
324 43
            ->issuer()
325 43
            ->equals($state->workingIssuerName())) {
326 1
            throw new PathValidationException("Certification issuer mismatch.");
327
        }
328 43
    }
329
    
330
    /**
331
     *
332
     * @param ValidatorState $state
333
     * @param Certificate $cert
334
     */
335 35
    private function _checkPermittedSubtrees(ValidatorState $state,
336
        Certificate $cert)
0 ignored issues
show
Unused Code introduced by
The parameter $cert is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
337
    {
338
        // @todo Implement
339 35
        $state->permittedSubtrees();
0 ignored issues
show
Unused Code introduced by
The call to the method X509\CertificationPath\P...te::permittedSubtrees() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
340 35
    }
341
    
342
    /**
343
     *
344
     * @param ValidatorState $state
345
     * @param Certificate $cert
346
     */
347 35
    private function _checkExcludedSubtrees(ValidatorState $state,
348
        Certificate $cert)
0 ignored issues
show
Unused Code introduced by
The parameter $cert is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
349
    {
350
        // @todo Implement
351 35
        $state->excludedSubtrees();
0 ignored issues
show
Unused Code introduced by
The call to the method X509\CertificationPath\P...ate::excludedSubtrees() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
352 35
    }
353
    
354
    /**
355
     * Apply policy mappings handling for the preparation step.
356
     *
357
     * @param ValidatorState $state
358
     * @param Certificate $cert
359
     * @throws PathValidationException
360
     * @return ValidatorState
361
     */
362 43
    private function _preparePolicyMappings(ValidatorState $state,
363
        Certificate $cert): ValidatorState
364
    {
365 43
        $extensions = $cert->tbsCertificate()->extensions();
366 43
        if ($extensions->hasPolicyMappings()) {
367
            // (a) verify that anyPolicy mapping is not used
368 4
            if ($extensions->policyMappings()->hasAnyPolicyMapping()) {
369 1
                throw new PathValidationException("anyPolicy mapping found.");
370
            }
371
            // (b) process policy mappings
372 3
            if ($state->hasValidPolicyTree()) {
373 3
                $state = $state->validPolicyTree()->processMappings($state,
374 3
                    $cert);
375
            }
376
        }
377 42
        return $state;
378
    }
379
    
380
    /**
381
     * Apply name constraints handling for the preparation step.
382
     *
383
     * @param ValidatorState $state
384
     * @param Certificate $cert
385
     * @return ValidatorState
386
     */
387 42
    private function _prepareNameConstraints(ValidatorState $state,
388
        Certificate $cert): ValidatorState
389
    {
390 42
        $extensions = $cert->tbsCertificate()->extensions();
391 42
        if ($extensions->hasNameConstraints()) {
392 1
            $state = $this->_processNameConstraints($state, $cert);
393
        }
394 42
        return $state;
395
    }
396
    
397
    /**
398
     * Apply preparation for a non-self-signed certificate.
399
     *
400
     * @param ValidatorState $state
401
     * @return ValidatorState
402
     */
403 21
    private function _prepareNonSelfIssued(ValidatorState $state): ValidatorState
404
    {
405
        // (h.1)
406 21
        if ($state->explicitPolicy() > 0) {
407 20
            $state = $state->withExplicitPolicy($state->explicitPolicy() - 1);
408
        }
409
        // (h.2)
410 21
        if ($state->policyMapping() > 0) {
411 20
            $state = $state->withPolicyMapping($state->policyMapping() - 1);
412
        }
413
        // (h.3)
414 21
        if ($state->inhibitAnyPolicy() > 0) {
415 21
            $state = $state->withInhibitAnyPolicy(
416 21
                $state->inhibitAnyPolicy() - 1);
417
        }
418 21
        return $state;
419
    }
420
    
421
    /**
422
     * Apply policy constraints handling for the preparation step.
423
     *
424
     * @param ValidatorState $state
425
     * @param Certificate $cert
426
     * @return ValidatorState
427
     */
428 42
    private function _preparePolicyConstraints(ValidatorState $state,
429
        Certificate $cert): ValidatorState
430
    {
431 42
        $extensions = $cert->tbsCertificate()->extensions();
432 42
        if (!$extensions->hasPolicyConstraints()) {
433 41
            return $state;
434
        }
435 2
        $ext = $extensions->policyConstraints();
436
        // (i.1)
437 2
        if ($ext->hasRequireExplicitPolicy() &&
438 2
             $ext->requireExplicitPolicy() < $state->explicitPolicy()) {
439 2
            $state = $state->withExplicitPolicy($ext->requireExplicitPolicy());
440
        }
441
        // (i.2)
442 2
        if ($ext->hasInhibitPolicyMapping() &&
443 2
             $ext->inhibitPolicyMapping() < $state->policyMapping()) {
444 1
            $state = $state->withPolicyMapping($ext->inhibitPolicyMapping());
445
        }
446 2
        return $state;
447
    }
448
    
449
    /**
450
     * Apply inhibit any-policy handling for the preparation step.
451
     *
452
     * @param ValidatorState $state
453
     * @param Certificate $cert
454
     * @return ValidatorState
455
     */
456 42
    private function _prepareInhibitAnyPolicy(ValidatorState $state,
457
        Certificate $cert): ValidatorState
458
    {
459 42
        $extensions = $cert->tbsCertificate()->extensions();
460 42
        if ($extensions->hasInhibitAnyPolicy()) {
461 2
            $ext = $extensions->inhibitAnyPolicy();
462 2
            if ($ext->skipCerts() < $state->inhibitAnyPolicy()) {
463 2
                $state = $state->withInhibitAnyPolicy($ext->skipCerts());
464
            }
465
        }
466 42
        return $state;
467
    }
468
    
469
    /**
470
     * Verify maximum certification path length for the preparation step.
471
     *
472
     * @param ValidatorState $state
473
     * @param Certificate $cert
474
     * @throws PathValidationException
475
     * @return ValidatorState
476
     */
477 40
    private function _verifyMaxPathLength(ValidatorState $state,
478
        Certificate $cert): ValidatorState
479
    {
480 40
        if (!$cert->isSelfIssued()) {
481 21
            if ($state->maxPathLength() <= 0) {
482 2
                throw new PathValidationException(
483 2
                    "Certification path length exceeded.");
484
            }
485 19
            $state = $state->withMaxPathLength($state->maxPathLength() - 1);
486
        }
487 40
        return $state;
488
    }
489
    
490
    /**
491
     * Check key usage extension for the preparation step.
492
     *
493
     * @param Certificate $cert
494
     * @throws PathValidationException
495
     */
496 40
    private function _checkKeyUsage(Certificate $cert)
497
    {
498 40
        $extensions = $cert->tbsCertificate()->extensions();
499 40
        if ($extensions->hasKeyUsage()) {
500 20
            $ext = $extensions->keyUsage();
501 20
            if (!$ext->isKeyCertSign()) {
502 1
                throw new PathValidationException("keyCertSign usage not set.");
503
            }
504
        }
505 39
    }
506
    
507
    /**
508
     *
509
     * @param ValidatorState $state
510
     * @param Certificate $cert
511
     * @return ValidatorState
512
     */
513 1
    private function _processNameConstraints(ValidatorState $state,
514
        Certificate $cert): ValidatorState
0 ignored issues
show
Unused Code introduced by
The parameter $cert is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
515
    {
516
        // @todo Implement
517 1
        return $state;
518
    }
519
    
520
    /**
521
     * Process basic constraints extension.
522
     *
523
     * @param Certificate $cert
524
     * @throws PathValidationException
525
     */
526 42
    private function _processBasicContraints(Certificate $cert)
527
    {
528 42
        if ($cert->tbsCertificate()->version() == TBSCertificate::VERSION_3) {
529 39
            $extensions = $cert->tbsCertificate()->extensions();
530 39
            if (!$extensions->hasBasicConstraints()) {
531 1
                throw new PathValidationException(
532 1
                    "v3 certificate must have basicConstraints extension.");
533
            }
534
            // verify that cA is set to TRUE
535 38
            if (!$extensions->basicConstraints()->isCA()) {
536 1
                throw new PathValidationException(
537 1
                    "Certificate is not a CA certificate.");
538
            }
539
        }
540 40
    }
541
    
542
    /**
543
     * Process pathLenConstraint.
544
     *
545
     * @param ValidatorState $state
546
     * @param Certificate $cert
547
     * @return ValidatorState
548
     */
549 40
    private function _processPathLengthContraint(ValidatorState $state,
550
        Certificate $cert): ValidatorState
551
    {
552 40
        $extensions = $cert->tbsCertificate()->extensions();
553 40
        if ($extensions->hasBasicConstraints()) {
554 37
            $ext = $extensions->basicConstraints();
555 37
            if ($ext->hasPathLen()) {
556 26
                if ($ext->pathLen() < $state->maxPathLength()) {
557 9
                    $state = $state->withMaxPathLength($ext->pathLen());
558
                }
559
            }
560
        }
561 40
        return $state;
562
    }
563
    
564
    /**
565
     *
566
     * @param ValidatorState $state
567
     * @param Certificate $cert
568
     * @return ValidatorState
569
     */
570 39
    private function _processExtensions(ValidatorState $state, Certificate $cert): ValidatorState
0 ignored issues
show
Unused Code introduced by
The parameter $cert is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
571
    {
572
        // @todo Implement
573 39
        return $state;
574
    }
575
    
576
    /**
577
     *
578
     * @param ValidatorState $state
579
     * @return ValidatorState
580
     */
581 30
    private function _calculatePolicyIntersection(ValidatorState $state): ValidatorState
582
    {
583
        // (i) If the valid_policy_tree is NULL, the intersection is NULL
584 30
        if (!$state->hasValidPolicyTree()) {
585 21
            return $state;
586
        }
587
        // (ii) If the valid_policy_tree is not NULL and
588
        // the user-initial-policy-set is any-policy, the intersection
589
        // is the entire valid_policy_tree
590 9
        $initial_policies = $this->_config->policySet();
591 9
        if (in_array(PolicyInformation::OID_ANY_POLICY, $initial_policies)) {
592 3
            return $state;
593
        }
594
        // (iii) If the valid_policy_tree is not NULL and the
595
        // user-initial-policy-set is not any-policy, calculate
596
        // the intersection of the valid_policy_tree and the
597
        // user-initial-policy-set as follows
598 6
        return $state->validPolicyTree()->calculateIntersection($state,
599 6
            $initial_policies);
600
    }
601
}
602