| Conditions | 19 |
| Paths | 104 |
| Total Lines | 99 |
| Code Lines | 49 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 3 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 148 | private function validateAttestationFormatPacked(array $attestationArray, string $clientDataJSON) : void |
||
| 149 | { |
||
| 150 | $stmtDecoded = $attestationArray['attStmt']; |
||
| 151 | $this->debugBuffer .= "AttStmt: " . print_r($stmtDecoded, true) . "<br/>"; |
||
| 152 | /** |
||
| 153 | * §7.1 Step 16: attestation is either done with x5c or ecdaa. |
||
| 154 | */ |
||
| 155 | if (isset($stmtDecoded['x5c'])) { |
||
| 156 | /** |
||
| 157 | * §8.2 Step 2: check x5c attestation |
||
| 158 | */ |
||
| 159 | $sigdata = $attestationArray['authData'] . hash("sha256", $clientDataJSON, true); |
||
| 160 | $keyResource = openssl_pkey_get_public($this->der2pem($stmtDecoded['x5c'][0])); |
||
| 161 | if ($keyResource === false) { |
||
| 162 | $this->fail("Unable to construct public key resource from PEM."); |
||
| 163 | } |
||
| 164 | /** |
||
| 165 | * §8.2 Step 2 Bullet 1: check signature |
||
| 166 | */ |
||
| 167 | if (openssl_verify($sigdata, $stmtDecoded['sig'], $keyResource, OPENSSL_ALGO_SHA256) != 1) { |
||
| 168 | $this->fail("x5c attestation failed."); |
||
| 169 | } |
||
| 170 | $this->pass("x5c sig check passed."); |
||
| 171 | // still need to perform sanity checks on the attestation certificate |
||
| 172 | /** |
||
| 173 | * §8.2 Step 2 Bullet 2: check certificate properties listed in §8.2.1 |
||
| 174 | */ |
||
| 175 | $certProps = openssl_x509_parse($this->der2pem($stmtDecoded['x5c'][0])); |
||
| 176 | $this->debugBuffer .= "Attestation Certificate:" . print_r($certProps, true) . "<br/>"; |
||
| 177 | if ($certProps['version'] != 2 || /** §8.2.1 Bullet 1 */ |
||
| 178 | $certProps['subject']['OU'] != "Authenticator Attestation" || /** §8.2.1 Bullet 2 [Subject-OU] */ |
||
| 179 | !isset($certProps['subject']['CN']) || /** §8.2.1 Bullet 2 [Subject-CN] */ |
||
| 180 | !isset($certProps['extensions']['basicConstraints']) || |
||
| 181 | strstr("CA:FALSE", $certProps['extensions']['basicConstraints']) === false /** §8.2.1 Bullet 4 */ |
||
| 182 | ) { |
||
| 183 | $this->fail("Attestation certificate properties are no good."); |
||
| 184 | } |
||
| 185 | if (isset(AAGUID::AAGUID_DICTIONARY[strtolower($this->AAGUID)])) { |
||
| 186 | if ($certProps['subject']['O'] != AAGUID::AAGUID_DICTIONARY[strtolower($this->AAGUID)]['O'] || /** §8.2.1 Bullet 2 [Subject-O] */ |
||
| 187 | $certProps['subject']['C'] != AAGUID::AAGUID_DICTIONARY[strtolower($this->AAGUID)]['C']) { /** §8.2.1 Bullet 2 [Subject-C] */ |
||
| 188 | $this->fail("AAGUID does not match vendor data."); |
||
| 189 | } |
||
| 190 | if (AAGUID::AAGUID_DICTIONARY[strtolower($this->AAGUID)]['multi'] === true) { // need to check the OID |
||
| 191 | if (!isset($certProps['extensions']['1.3.6.1.4.1.45724.1.1.4'])) { /** §8.2.1 Bullet 3 */ |
||
| 192 | $this->fail("This vendor uses one cert for multiple authenticator model attestations, but lacks the AAGUID OID."); |
||
| 193 | } |
||
| 194 | /** |
||
| 195 | * §8.2 Step 2 Bullet 3: compare AAGUID values |
||
| 196 | */ |
||
| 197 | $AAGUIDFromOid = substr(bin2hex($certProps['extensions']['1.3.6.1.4.1.45724.1.1.4']), 4); |
||
| 198 | $this->debugBuffer .= "AAGUID from OID = $AAGUIDFromOid<br/>"; |
||
| 199 | if (strtolower($AAGUIDFromOid) != strtolower($this->AAGUID)) { |
||
| 200 | $this->fail("AAGUID mismatch between attestation certificate and attestation statement."); |
||
| 201 | } |
||
| 202 | } |
||
| 203 | // we would need to verify the attestation certificate against a known-good root CA certificate to get more than basic |
||
| 204 | /* |
||
| 205 | * §7.1 Step 17 is to look at AAGUID::AAGUID_DICTIONARY[strtolower($this->AAGUID)]['RootPEMs'] |
||
| 206 | */ |
||
| 207 | /* |
||
| 208 | * §7.1 Step 18 is skipped, and we unconditionally return "only" Basic. |
||
| 209 | */ |
||
| 210 | $this->AAGUIDAssurance = WebAuthnRegistrationEvent::AAGUID_ASSURANCE_LEVEL_BASIC; |
||
| 211 | } else { |
||
| 212 | $this->warn("Unknown authenticator model found: " . $this->AAGUID . "."); |
||
| 213 | // unable to verify all cert properties, so this is not enough for BASIC. |
||
| 214 | // but it's our own fault, we should add the device to our DB. |
||
| 215 | $this->AAGUIDAssurance = WebAuthnRegistrationEvent::AAGUID_ASSURANCE_LEVEL_SELF; |
||
| 216 | } |
||
| 217 | $this->pass("x5c attestation passed."); |
||
| 218 | return; |
||
| 219 | } |
||
| 220 | if (isset($stmtDecoded['ecdaa'])) { |
||
| 221 | $this->fail("ecdaa attestation not supported right now."); |
||
| 222 | } |
||
| 223 | // if we are still here, we are in the "self" type. |
||
| 224 | /** |
||
| 225 | * §8.2 Step 4 Bullet 1: check algorithm |
||
| 226 | */ |
||
| 227 | if ($stmtDecoded['alg'] != WebAuthnRegistrationEvent::PK_ALGORITHM) { |
||
| 228 | $this->fail("Unexpected algorithm type in packed basic attestation: " . $stmtDecoded['alg'] . "."); |
||
| 229 | } |
||
| 230 | $keyObject = new Ec2Key($this->cborDecode(hex2bin($this->credential))); |
||
| 231 | $keyResource = openssl_pkey_get_public($keyObject->asPEM()); |
||
| 232 | if ($keyResource === false) { |
||
| 233 | $this->fail("Unable to construct public key resource from PEM."); |
||
| 234 | } |
||
| 235 | $sigdata = $attestationArray['authData'] . $this->clientDataHash; |
||
| 236 | /** |
||
| 237 | * §8.2 Step 4 Bullet 2: verify signature |
||
| 238 | */ |
||
| 239 | if (openssl_verify($sigdata, $stmtDecoded['sig'], $keyResource, OPENSSL_ALGO_SHA256) == 1) { |
||
| 240 | $this->pass("Self-Attestation veried."); |
||
| 241 | /** |
||
| 242 | * §8.2 Step 4 Bullet 3: return Self level |
||
| 243 | */ |
||
| 244 | $this->AAGUIDAssurance = WebAuthnRegistrationEvent::AAGUID_ASSURANCE_LEVEL_SELF; |
||
| 245 | } else { |
||
| 246 | $this->fail("Self-Attestation failed."); |
||
| 247 | } |
||
| 326 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.