Passed
Push — master ( 74c929...60a713 )
by Stefan
10:18
created
lib/WebAuthn/WebAuthnRegistrationEvent.php 1 patch
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -118,9 +118,9 @@  discard block
 block discarded – undo
118 118
             case "android-safetynet":
119 119
                 $this->validateAttestationFormatAndroidSafetyNet($attestationArray);
120 120
                 break;
121
-	    case "apple":
122
-		$this->validateAttestationFormatApple($attestationArray);
123
-		break;
121
+        case "apple":
122
+        $this->validateAttestationFormatApple($attestationArray);
123
+        break;
124 124
             case "tpm":
125 125
             case "android-key":
126 126
                 $this->fail("Attestation format " . $attestationArray['fmt'] . " validation not supported right now.");
@@ -158,9 +158,9 @@  discard block
 block discarded – undo
158 158
     private function validateAttestationFormatApple(array $attestationArray): void
159 159
     {
160 160
 
161
-	// found at: https://www.apple.com/certificateauthority/private/
161
+    // found at: https://www.apple.com/certificateauthority/private/
162 162
 
163
-	$APPLE_WEBAUTHN_ROOT_CA = "-----BEGIN CERTIFICATE-----
163
+    $APPLE_WEBAUTHN_ROOT_CA = "-----BEGIN CERTIFICATE-----
164 164
 MIICEjCCAZmgAwIBAgIQaB0BbHo84wIlpQGUKEdXcTAKBggqhkjOPQQDAzBLMR8w
165 165
 HQYDVQQDDBZBcHBsZSBXZWJBdXRobiBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ
166 166
 bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTIwMDMxODE4MjEzMloXDTQ1MDMx
@@ -175,66 +175,66 @@  discard block
 block discarded – undo
175 175
 1bWeT0vT
176 176
 -----END CERTIFICATE-----";
177 177
         // § 8.8 Bullet 1 of the draft spec at https://pr-preview.s3.amazonaws.com/alanwaketan/webauthn/pull/1491.html#sctn-apple-anonymous-attestation
178
-	// draft implemented in state of 11 Feb 2021
178
+    // draft implemented in state of 11 Feb 2021
179 179
 
180
-	// I can't help but notice that the verification procedure does NOTHING with CA certs from the chain, nor is there a root to validate to!
181
-	// Found the root CA with Google, see above, and will perform chain validation even if the spec doesn't say so.
180
+    // I can't help but notice that the verification procedure does NOTHING with CA certs from the chain, nor is there a root to validate to!
181
+    // Found the root CA with Google, see above, and will perform chain validation even if the spec doesn't say so.
182 182
 
183
-	// first, clear the openssl error backlog. We might need error data in case things go sideways.
184
-	while(openssl_error_string() !== false);
183
+    // first, clear the openssl error backlog. We might need error data in case things go sideways.
184
+    while(openssl_error_string() !== false);
185 185
 
186 186
         $stmtDecoded = $attestationArray['attStmt'];
187
-	if (!isset($stmtDecoded['x5c'])) {
188
-		$this->fail("Apple attestation statement does not contain an x5c attestation statement!");
189
-	}
190
-	// § 8.8 Bullet 2
187
+    if (!isset($stmtDecoded['x5c'])) {
188
+        $this->fail("Apple attestation statement does not contain an x5c attestation statement!");
189
+    }
190
+    // § 8.8 Bullet 2
191 191
         $nonceToHash = $attestationArray['authData'] . $this->clientDataHash;
192
-	// § 8.8 Bullet 3
193
-	$nonce = hash("sha256", $nonceToHash, TRUE); // does raw_output have to be FALSE or TRUE?
192
+    // § 8.8 Bullet 3
193
+    $nonce = hash("sha256", $nonceToHash, TRUE); // does raw_output have to be FALSE or TRUE?
194 194
         $certProps = openssl_x509_parse(Utils\Crypto::der2pem($stmtDecoded['x5c'][0]));	
195
-	// § 8.8 Bullet 4
195
+    // § 8.8 Bullet 4
196 196
         if (
197
-           !isset($certProps['extensions']['1.2.840.113635.100.8.2'])
197
+            !isset($certProps['extensions']['1.2.840.113635.100.8.2'])
198 198
            || empty($certProps['extensions']['1.2.840.113635.100.8.2'])
199 199
                 ) {
200 200
                     $this->fail( "The required nonce value is not present in the OID." );
201 201
                 }
202
-	$toCompare = substr($certProps['extensions']['1.2.840.113635.100.8.2'], 6);
203
-	if ($nonce != $toCompare) {
204
-		$this->fail("There is a mismatch between the nonce and the OID (XXX $nonce XXX , XXX $toCompare XXX ).");
205
-	}
206
-
207
-	// chain validation first
208
-	foreach ( $stmtDecoded['x5c'] as $runIndex => $runCert ) {
209
-		if (isset($stmtDecoded['x5c'][$runIndex + 1])) { // there is a next cert, so follow the chain
210
-			$certResource = openssl_x509_read(Utils\Crypto::der2pem($runCert));
211
-			$signerPubKey = openssl_pkey_get_public(Utils\Crypto::der2pem($stmtDecoded['x5c'][$runIndex + 1]));
212
-			if (openssl_x509_verify($certResource, $signerPubKey) != 1) {
213
-				$this->fail("Error during chain validation of the attestation certificate (while validating cert #$runIndex, which is "
202
+    $toCompare = substr($certProps['extensions']['1.2.840.113635.100.8.2'], 6);
203
+    if ($nonce != $toCompare) {
204
+        $this->fail("There is a mismatch between the nonce and the OID (XXX $nonce XXX , XXX $toCompare XXX ).");
205
+    }
206
+
207
+    // chain validation first
208
+    foreach ( $stmtDecoded['x5c'] as $runIndex => $runCert ) {
209
+        if (isset($stmtDecoded['x5c'][$runIndex + 1])) { // there is a next cert, so follow the chain
210
+            $certResource = openssl_x509_read(Utils\Crypto::der2pem($runCert));
211
+            $signerPubKey = openssl_pkey_get_public(Utils\Crypto::der2pem($stmtDecoded['x5c'][$runIndex + 1]));
212
+            if (openssl_x509_verify($certResource, $signerPubKey) != 1) {
213
+                $this->fail("Error during chain validation of the attestation certificate (while validating cert #$runIndex, which is "
214 214
                                     . Utils\Crypto::der2pem($runCert)
215 215
                                     . "; next cert was "
216 216
                                     . Utils\Crypto::der2pem($stmtDecoded['x5c'][$runIndex + 1]));
217
-			}
218
-		} else { // last cert, compare to the root
219
-			$certResource = openssl_x509_read(Utils\Crypto::der2pem($runCert));
220
-			$signerPubKey = openssl_pkey_get_public($APPLE_WEBAUTHN_ROOT_CA);
221
-			if (openssl_x509_verify($certResource, $signerPubKey) != 1) {
217
+            }
218
+        } else { // last cert, compare to the root
219
+            $certResource = openssl_x509_read(Utils\Crypto::der2pem($runCert));
220
+            $signerPubKey = openssl_pkey_get_public($APPLE_WEBAUTHN_ROOT_CA);
221
+            if (openssl_x509_verify($certResource, $signerPubKey) != 1) {
222 222
                                 $this->fail("Error during root CA validation of the attestation chain certificate, which is ".Utils\Crypto::der2pem($runCert));
223 223
                         }
224
-		}
225
-	}
224
+        }
225
+    }
226 226
 
227 227
         $keyResource = openssl_pkey_get_public(Utils\Crypto::der2pem($stmtDecoded['x5c'][0]));
228 228
         if ($keyResource === FALSE) {
229
-		$this->fail("Did not get a parseable X.509 structure out of the Apple attestation statement - x5c nr. 0 statement was: XXX "
229
+        $this->fail("Did not get a parseable X.509 structure out of the Apple attestation statement - x5c nr. 0 statement was: XXX "
230 230
                     . $stmtDecoded['x5c'][0]
231 231
                     . " XXX; PEM equivalent is "
232 232
                     . Utils\Crypto::der2pem($stmtDecoded['x5c'][0])
233 233
                     . ". OpenSSL error: "
234 234
                     . openssl_error_string()
235 235
                     );
236
-	}
237
-	// $this->credential is a public key in CBOR, not "PEM". We need to convert it first.
236
+    }
237
+    // $this->credential is a public key in CBOR, not "PEM". We need to convert it first.
238 238
         $keyArray = $this->cborDecode(hex2bin($this->credential));
239 239
         $keyObject = new Ec2Key($keyArray);
240 240
         $credentialResource = openssl_pkey_get_public($keyObject->asPEM());
@@ -248,20 +248,20 @@  discard block
 block discarded – undo
248 248
                     . openssl_error_string()
249 249
                     );
250 250
         }
251
-	// § 8.8 Bullet 5
252
-	$credentialDetails = openssl_pkey_get_details($credentialResource);
253
-	$keyDetails = openssl_pkey_get_details($keyResource);
254
-	if ( $credentialDetails['bits'] != $keyDetails['bits'] ||
251
+    // § 8.8 Bullet 5
252
+    $credentialDetails = openssl_pkey_get_details($credentialResource);
253
+    $keyDetails = openssl_pkey_get_details($keyResource);
254
+    if ( $credentialDetails['bits'] != $keyDetails['bits'] ||
255 255
              $credentialDetails['key']  != $keyDetails['key']  ||
256 256
              $credentialDetails['type'] != $keyDetails['type'] ) { 
257
-		$this->fail("The credential public key does not match the certificate public key in attestationData. ("
258
-              . $credentialDetails['key'] 
259
-              . " - "
260
-              . $keyDetails['key'] 
261
-              . ")");
262
-	}
263
-	$this->pass("Apple attestation format verification passed.");
264
-	return;
257
+        $this->fail("The credential public key does not match the certificate public key in attestationData. ("
258
+                . $credentialDetails['key'] 
259
+                . " - "
260
+                . $keyDetails['key'] 
261
+                . ")");
262
+    }
263
+    $this->pass("Apple attestation format verification passed.");
264
+    return;
265 265
     }
266 266
 
267 267
     /**
Please login to merge, or discard this patch.