PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.5.0
Defender Security – Malware Scanner, Login Security & Firewall v5.5.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / vendor / web-auth / webauthn-lib / src / AttestationStatement / AttestationObjectLoader.php

AttestationObjectLoader.php in Defender Security – Malware Scanner, Login Security & Firewall 5.5.0, at vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php

149 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 /*
6 * The MIT License (MIT)
7 *
8 * Copyright (c) 2014-2021 Spomky-Labs
9 *
10 * This software may be modified and distributed under the terms
11 * of the MIT license. See the LICENSE file for details.
12 */
13
14 namespace Webauthn\AttestationStatement;
15
16 use Assert\Assertion;
17 use Base64Url\Base64Url;
18 use CBOR\Decoder;
19 use CBOR\MapObject;
20 use CBOR\OtherObject\OtherObjectManager;
21 use CBOR\Tag\TagObjectManager;
22 use function ord;
23 use Psr\Log\LoggerInterface;
24 use Psr\Log\NullLogger;
25 use Ramsey\Uuid\Uuid;
26 use function Safe\sprintf;
27 use function Safe\unpack;
28 use Throwable;
29 use Webauthn\AttestedCredentialData;
30 use Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientOutputsLoader;
31 use Webauthn\AuthenticatorData;
32 use Webauthn\MetadataService\MetadataStatementRepository;
33 use Webauthn\StringStream;
34
35 class AttestationObjectLoader
36 {
37 private const FLAG_AT = 0b01000000;
38 private const FLAG_ED = 0b10000000;
39
40 /**
41 * @var Decoder
42 */
43 private $decoder;
44
45 /**
46 * @var AttestationStatementSupportManager
47 */
48 private $attestationStatementSupportManager;
49
50 /**
51 * @var LoggerInterface|null
52 */
53 private $logger;
54
55 public function __construct(AttestationStatementSupportManager $attestationStatementSupportManager, ?MetadataStatementRepository $metadataStatementRepository = null, ?LoggerInterface $logger = null)
56 {
57 if (null !== $metadataStatementRepository) {
58 @trigger_error('The argument "metadataStatementRepository" is deprecated since version 3.2 and will be removed in 4.0. Please set `null` instead.', E_USER_DEPRECATED);
59 }
60 if (null !== $logger) {
61 @trigger_error('The argument "logger" is deprecated since version 3.3 and will be removed in 4.0. Please use the method "setLogger" instead.', E_USER_DEPRECATED);
62 }
63 $this->decoder = new Decoder(new TagObjectManager(), new OtherObjectManager());
64 $this->attestationStatementSupportManager = $attestationStatementSupportManager;
65 $this->logger = $logger ?? new NullLogger();
66 }
67
68 public static function create(AttestationStatementSupportManager $attestationStatementSupportManager): self
69 {
70 return new self($attestationStatementSupportManager);
71 }
72
73 public function load(string $data): AttestationObject
74 {
75 try {
76 $this->logger->info('Trying to load the data', ['data' => $data]);
77 $decodedData = Base64Url::decode($data);
78 $stream = new StringStream($decodedData);
79 $parsed = $this->decoder->decode($stream);
80
81 $this->logger->info('Loading the Attestation Statement');
82 $attestationObject = $parsed->getNormalizedData();
83 Assertion::true($stream->isEOF(), 'Invalid attestation object. Presence of extra bytes.');
84 $stream->close();
85 Assertion::isArray($attestationObject, 'Invalid attestation object');
86 Assertion::keyExists($attestationObject, 'authData', 'Invalid attestation object');
87 Assertion::keyExists($attestationObject, 'fmt', 'Invalid attestation object');
88 Assertion::keyExists($attestationObject, 'attStmt', 'Invalid attestation object');
89 $authData = $attestationObject['authData'];
90
91 $attestationStatementSupport = $this->attestationStatementSupportManager->get($attestationObject['fmt']);
92 $attestationStatement = $attestationStatementSupport->load($attestationObject);
93 $this->logger->info('Attestation Statement loaded');
94 $this->logger->debug('Attestation Statement loaded', ['attestationStatement' => $attestationStatement]);
95
96 $authDataStream = new StringStream($authData);
97 $rp_id_hash = $authDataStream->read(32);
98 $flags = $authDataStream->read(1);
99 $signCount = $authDataStream->read(4);
100 $signCount = unpack('N', $signCount)[1];
101 $this->logger->debug(sprintf('Signature counter: %d', $signCount));
102
103 $attestedCredentialData = null;
104 if (0 !== (ord($flags) & self::FLAG_AT)) {
105 $this->logger->info('Attested Credential Data is present');
106 $aaguid = Uuid::fromBytes($authDataStream->read(16));
107 $credentialLength = $authDataStream->read(2);
108 $credentialLength = unpack('n', $credentialLength)[1];
109 $credentialId = $authDataStream->read($credentialLength);
110 $credentialPublicKey = $this->decoder->decode($authDataStream);
111 Assertion::isInstanceOf($credentialPublicKey, MapObject::class, 'The data does not contain a valid credential public key.');
112 $attestedCredentialData = new AttestedCredentialData($aaguid, $credentialId, (string) $credentialPublicKey);
113 $this->logger->info('Attested Credential Data loaded');
114 $this->logger->debug('Attested Credential Data loaded', ['at' => $attestedCredentialData]);
115 }
116
117 $extension = null;
118 if (0 !== (ord($flags) & self::FLAG_ED)) {
119 $this->logger->info('Extension Data loaded');
120 $extension = $this->decoder->decode($authDataStream);
121 $extension = AuthenticationExtensionsClientOutputsLoader::load($extension);
122 $this->logger->info('Extension Data loaded');
123 $this->logger->debug('Extension Data loaded', ['ed' => $extension]);
124 }
125 Assertion::true($authDataStream->isEOF(), 'Invalid authentication data. Presence of extra bytes.');
126 $authDataStream->close();
127
128 $authenticatorData = new AuthenticatorData($authData, $rp_id_hash, $flags, $signCount, $attestedCredentialData, $extension);
129 $attestationObject = new AttestationObject($data, $attestationStatement, $authenticatorData);
130 $this->logger->info('Attestation Object loaded');
131 $this->logger->debug('Attestation Object', ['ed' => $attestationObject]);
132
133 return $attestationObject;
134 } catch (Throwable $throwable) {
135 $this->logger->error('An error occurred', [
136 'exception' => $throwable,
137 ]);
138 throw $throwable;
139 }
140 }
141
142 public function setLogger(LoggerInterface $logger): self
143 {
144 $this->logger = $logger;
145
146 return $this;
147 }
148 }
149