ValidatorState   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 483
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 35
lcom 1
cbo 10
dl 0
loc 483
ccs 103
cts 103
cp 1
rs 9.6
c 0
b 0
f 0

30 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A initialize() 0 21 4
A withIndex() 0 6 1
A withValidPolicyTree() 0 6 1
A withoutValidPolicyTree() 0 6 1
A withExplicitPolicy() 0 6 1
A withInhibitAnyPolicy() 0 6 1
A withPolicyMapping() 0 6 1
A withWorkingPublicKeyAlgorithm() 0 6 1
A withWorkingPublicKey() 0 6 1
A withWorkingPublicKeyParameters() 0 6 1
A withWorkingIssuerName() 0 6 1
A withMaxPathLength() 0 6 1
A pathLength() 0 4 1
A index() 0 4 1
A hasValidPolicyTree() 0 4 1
A validPolicyTree() 0 7 2
A permittedSubtrees() 0 4 1
A excludedSubtrees() 0 4 1
A explicitPolicy() 0 4 1
A inhibitAnyPolicy() 0 4 1
A policyMapping() 0 4 1
A workingPublicKeyAlgorithm() 0 4 1
A workingPublicKey() 0 4 1
A workingPublicKeyParameters() 0 4 1
A workingIssuerName() 0 4 1
A maxPathLength() 0 4 1
A isFinal() 0 4 1
A getResult() 0 6 1
A getAlgorithmParameters() 0 5 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace X509\CertificationPath\PathValidation;
6
7
use ASN1\Element;
8
use Sop\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
9
use Sop\CryptoTypes\Asymmetric\PublicKeyInfo;
10
use X501\ASN1\Name;
11
use X509\Certificate\Certificate;
12
use X509\CertificationPath\Policy\PolicyNode;
13
use X509\CertificationPath\Policy\PolicyTree;
14
15
/**
16
 * State class for the certification path validation process.
17
 *
18
 * @link https://tools.ietf.org/html/rfc5280#section-6.1.1
19
 * @link https://tools.ietf.org/html/rfc5280#section-6.1.2
20
 */
21
class ValidatorState
22
{
23
    /**
24
     * Length of the certification path (n).
25
     *
26
     * @var int $_pathLength
27
     */
28
    protected $_pathLength;
29
    
30
    /**
31
     * Current index in the certification path in the range of 1..n (i).
32
     *
33
     * @var int $_index
34
     */
35
    protected $_index;
36
    
37
    /**
38
     * Valid policy tree (valid_policy_tree).
39
     *
40
     * A tree of certificate policies with their optional qualifiers.
41
     * Each of the leaves of the tree represents a valid policy at this stage in
42
     * the certification path validation.
43
     * Once the tree is set to NULL, policy processing ceases.
44
     *
45
     * @var PolicyTree|null $_validPolicyTree
46
     */
47
    protected $_validPolicyTree;
48
    
49
    /**
50
     * Permitted subtrees (permitted_subtrees).
51
     *
52
     * A set of root names for each name type defining a set of subtrees within
53
     * which all subject names in subsequent certificates in the certification
54
     * path must fall.
55
     *
56
     * @var mixed $_permittedSubtrees
57
     */
58
    protected $_permittedSubtrees;
59
    
60
    /**
61
     * Excluded subtrees (excluded_subtrees).
62
     *
63
     * A set of root names for each name type defining a set of subtrees within
64
     * which no subject name in subsequent certificates in the certification
65
     * path may fall.
66
     *
67
     * @var mixed $_excludedSubtrees
68
     */
69
    protected $_excludedSubtrees;
70
    
71
    /**
72
     * Explicit policy (explicit_policy).
73
     *
74
     * An integer that indicates if a non-NULL valid_policy_tree is required.
75
     *
76
     * @var int $_explicitPolicy
77
     */
78
    protected $_explicitPolicy;
79
    
80
    /**
81
     * Inhibit anyPolicy (inhibit_anyPolicy).
82
     *
83
     * An integer that indicates whether the anyPolicy policy identifier is
84
     * considered a match.
85
     *
86
     * @var int $_inhibitAnyPolicy
87
     */
88
    protected $_inhibitAnyPolicy;
89
    
90
    /**
91
     * Policy mapping (policy_mapping).
92
     *
93
     * An integer that indicates if policy mapping is permitted.
94
     *
95
     * @var int $_policyMapping
96
     */
97
    protected $_policyMapping;
98
    
99
    /**
100
     * Working public key algorithm (working_public_key_algorithm).
101
     *
102
     * The digital signature algorithm used to verify the signature of a
103
     * certificate.
104
     *
105
     * @var AlgorithmIdentifierType $_workingPublicKeyAlgorithm
106
     */
107
    protected $_workingPublicKeyAlgorithm;
108
    
109
    /**
110
     * Working public key (working_public_key).
111
     *
112
     * The public key used to verify the signature of a certificate.
113
     *
114
     * @var PublicKeyInfo $_workingPublicKey
115
     */
116
    protected $_workingPublicKey;
117
    
118
    /**
119
     * Working public key parameters (working_public_key_parameters).
120
     *
121
     * Parameters associated with the current public key that may be required to
122
     * verify a signature.
123
     *
124
     * @var Element|null $_workingPublicKeyParameters
125
     */
126
    protected $_workingPublicKeyParameters;
127
    
128
    /**
129
     * Working issuer name (working_issuer_name).
130
     *
131
     * The issuer distinguished name expected in the next certificate in the
132
     * chain.
133
     *
134
     * @var Name $_workingIssuerName
135
     */
136
    protected $_workingIssuerName;
137
    
138
    /**
139
     * Maximum certification path length (max_path_length).
140
     *
141
     * @var int $_maxPathLength
142
     */
143
    protected $_maxPathLength;
144
    
145
    /**
146
     * Constructor.
147
     */
148 47
    protected function __construct()
149
    {
150 47
    }
151
    
152
    /**
153
     * Initialize variables according to RFC 5280 6.1.2.
154
     *
155
     * @link https://tools.ietf.org/html/rfc5280#section-6.1.2
156
     * @param PathValidationConfig $config
157
     * @param Certificate $trust_anchor Trust anchor certificate
158
     * @param int $n Number of certificates in the certification path
159
     * @return self
160
     */
161 47
    public static function initialize(PathValidationConfig $config,
162
        Certificate $trust_anchor, $n)
163
    {
164 47
        $state = new self();
165 47
        $state->_pathLength = $n;
166 47
        $state->_index = 1;
167 47
        $state->_validPolicyTree = new PolicyTree(PolicyNode::anyPolicyNode());
168 47
        $state->_permittedSubtrees = null;
169 47
        $state->_excludedSubtrees = null;
170 47
        $state->_explicitPolicy = $config->explicitPolicy() ? 0 : $n + 1;
171 47
        $state->_inhibitAnyPolicy = $config->anyPolicyInhibit() ? 0 : $n + 1;
172 47
        $state->_policyMapping = $config->policyMappingInhibit() ? 0 : $n + 1;
173 47
        $state->_workingPublicKeyAlgorithm = $trust_anchor->signatureAlgorithm();
174 47
        $tbsCert = $trust_anchor->tbsCertificate();
175 47
        $state->_workingPublicKey = $tbsCert->subjectPublicKeyInfo();
176 47
        $state->_workingPublicKeyParameters = self::getAlgorithmParameters(
177 47
            $state->_workingPublicKey->algorithmIdentifier());
178 47
        $state->_workingIssuerName = $tbsCert->issuer();
179 47
        $state->_maxPathLength = $config->maxLength();
180 47
        return $state;
181
    }
182
    
183
    /**
184
     * Get self with current certification path index set.
185
     *
186
     * @param int $index
187
     * @return self
188
     */
189 44
    public function withIndex(int $index): self
190
    {
191 44
        $state = clone $this;
192 44
        $state->_index = $index;
193 44
        return $state;
194
    }
195
    
196
    /**
197
     * Get self with valid_policy_tree.
198
     *
199
     * @param PolicyTree $policy_tree
200
     * @return self
201
     */
202 14
    public function withValidPolicyTree(PolicyTree $policy_tree): self
203
    {
204 14
        $state = clone $this;
205 14
        $state->_validPolicyTree = $policy_tree;
206 14
        return $state;
207
    }
208
    
209
    /**
210
     * Get self with valid_policy_tree set to null.
211
     *
212
     * @return self
213
     */
214 36
    public function withoutValidPolicyTree(): self
215
    {
216 36
        $state = clone $this;
217 36
        $state->_validPolicyTree = null;
218 36
        return $state;
219
    }
220
    
221
    /**
222
     * Get self with explicit_policy.
223
     *
224
     * @param int $num
225
     * @return self
226
     */
227 30
    public function withExplicitPolicy(int $num): self
228
    {
229 30
        $state = clone $this;
230 30
        $state->_explicitPolicy = $num;
231 30
        return $state;
232
    }
233
    
234
    /**
235
     * Get self with inhibit_anyPolicy.
236
     *
237
     * @param int $num
238
     * @return self
239
     */
240 23
    public function withInhibitAnyPolicy(int $num): self
241
    {
242 23
        $state = clone $this;
243 23
        $state->_inhibitAnyPolicy = $num;
244 23
        return $state;
245
    }
246
    
247
    /**
248
     * Get self with policy_mapping.
249
     *
250
     * @param int $num
251
     * @return self
252
     */
253 21
    public function withPolicyMapping(int $num): self
254
    {
255 21
        $state = clone $this;
256 21
        $state->_policyMapping = $num;
257 21
        return $state;
258
    }
259
    
260
    /**
261
     * Get self with working_public_key_algorithm.
262
     *
263
     * @param AlgorithmIdentifierType $algo
264
     * @return self
265
     */
266 42
    public function withWorkingPublicKeyAlgorithm(AlgorithmIdentifierType $algo): self
267
    {
268 42
        $state = clone $this;
269 42
        $state->_workingPublicKeyAlgorithm = $algo;
270 42
        return $state;
271
    }
272
    
273
    /**
274
     * Get self with working_public_key.
275
     *
276
     * @param PublicKeyInfo $pubkey_info
277
     * @return self
278
     */
279 42
    public function withWorkingPublicKey(PublicKeyInfo $pubkey_info): self
280
    {
281 42
        $state = clone $this;
282 42
        $state->_workingPublicKey = $pubkey_info;
283 42
        return $state;
284
    }
285
    
286
    /**
287
     * Get self with working_public_key_parameters.
288
     *
289
     * @param Element|null $params
290
     * @return self
291
     */
292 42
    public function withWorkingPublicKeyParameters(Element $params = null): self
293
    {
294 42
        $state = clone $this;
295 42
        $state->_workingPublicKeyParameters = $params;
296 42
        return $state;
297
    }
298
    
299
    /**
300
     * Get self with working_issuer_name.
301
     *
302
     * @param Name $issuer
303
     * @return self
304
     */
305 42
    public function withWorkingIssuerName(Name $issuer): self
306
    {
307 42
        $state = clone $this;
308 42
        $state->_workingIssuerName = $issuer;
309 42
        return $state;
310
    }
311
    
312
    /**
313
     * Get self with max_path_length.
314
     *
315
     * @param int $length
316
     * @return self
317
     */
318 28
    public function withMaxPathLength(int $length): self
319
    {
320 28
        $state = clone $this;
321 28
        $state->_maxPathLength = $length;
322 28
        return $state;
323
    }
324
    
325
    /**
326
     * Get the certification path length (n).
327
     *
328
     * @return int
329
     */
330 1
    public function pathLength(): int
331
    {
332 1
        return $this->_pathLength;
333
    }
334
    
335
    /**
336
     * Get the current index in certification path in the range of 1..n.
337
     *
338
     * @return int
339
     */
340 15
    public function index(): int
341
    {
342 15
        return $this->_index;
343
    }
344
    
345
    /**
346
     * Check whether valid_policy_tree is present.
347
     *
348
     * @return bool
349
     */
350 35
    public function hasValidPolicyTree(): bool
351
    {
352 35
        return isset($this->_validPolicyTree);
353
    }
354
    
355
    /**
356
     * Get valid_policy_tree.
357
     *
358
     * @throws \LogicException
359
     * @return PolicyTree
360
     */
361 15
    public function validPolicyTree(): PolicyTree
362
    {
363 15
        if (!$this->hasValidPolicyTree()) {
364 1
            throw new \LogicException("valid_policy_tree not set.");
365
        }
366 14
        return $this->_validPolicyTree;
367
    }
368
    
369
    /**
370
     * Get permitted_subtrees.
371
     *
372
     * @return mixed
373
     */
374 35
    public function permittedSubtrees()
375
    {
376 35
        return $this->_permittedSubtrees;
377
    }
378
    
379
    /**
380
     * Get excluded_subtrees.
381
     *
382
     * @return mixed
383
     */
384 35
    public function excludedSubtrees()
385
    {
386 35
        return $this->_excludedSubtrees;
387
    }
388
    
389
    /**
390
     * Get explicit_policy.
391
     *
392
     * @return int
393
     */
394 43
    public function explicitPolicy(): int
395
    {
396 43
        return $this->_explicitPolicy;
397
    }
398
    
399
    /**
400
     * Get inhibit_anyPolicy.
401
     *
402
     * @return int
403
     */
404 26
    public function inhibitAnyPolicy(): int
405
    {
406 26
        return $this->_inhibitAnyPolicy;
407
    }
408
    
409
    /**
410
     * Get policy_mapping.
411
     *
412
     * @return int
413
     */
414 23
    public function policyMapping(): int
415
    {
416 23
        return $this->_policyMapping;
417
    }
418
    
419
    /**
420
     * Get working_public_key_algorithm.
421
     *
422
     * @return AlgorithmIdentifierType
423
     */
424 1
    public function workingPublicKeyAlgorithm(): AlgorithmIdentifierType
425
    {
426 1
        return $this->_workingPublicKeyAlgorithm;
427
    }
428
    
429
    /**
430
     * Get working_public_key.
431
     *
432
     * @return PublicKeyInfo
433
     */
434 44
    public function workingPublicKey(): PublicKeyInfo
435
    {
436 44
        return $this->_workingPublicKey;
437
    }
438
    
439
    /**
440
     * Get working_public_key_parameters.
441
     *
442
     * @return Element|null
443
     */
444 1
    public function workingPublicKeyParameters()
445
    {
446 1
        return $this->_workingPublicKeyParameters;
447
    }
448
    
449
    /**
450
     * Get working_issuer_name.
451
     *
452
     * @return Name
453
     */
454 43
    public function workingIssuerName(): Name
455
    {
456 43
        return $this->_workingIssuerName;
457
    }
458
    
459
    /**
460
     * Get maximum certification path length.
461
     *
462
     * @return int
463
     */
464 31
    public function maxPathLength(): int
465
    {
466 31
        return $this->_maxPathLength;
467
    }
468
    
469
    /**
470
     * Check whether processing the final certificate of the certification path.
471
     *
472
     * @return bool
473
     */
474 43
    public function isFinal(): bool
475
    {
476 43
        return $this->_index == $this->_pathLength;
477
    }
478
    
479
    /**
480
     * Get the path validation result.
481
     *
482
     * @param Certificate[] $certificates Certificates in a certification path
483
     * @return PathValidationResult
484
     */
485 28
    public function getResult(array $certificates): PathValidationResult
486
    {
487 28
        return new PathValidationResult($certificates, $this->_validPolicyTree,
488 28
            $this->_workingPublicKey, $this->_workingPublicKeyAlgorithm,
489 28
            $this->_workingPublicKeyParameters);
490
    }
491
    
492
    /**
493
     * Get ASN.1 parameters from algorithm identifier.
494
     *
495
     * @param AlgorithmIdentifierType $algo
496
     * @return Element|null ASN.1 element or null if parameters are omitted
497
     */
498 47
    public static function getAlgorithmParameters(AlgorithmIdentifierType $algo)
499
    {
500 47
        $seq = $algo->toASN1();
501 47
        return $seq->has(1) ? $seq->at(1)->asElement() : null;
502
    }
503
}
504