/** * Verifies that the Merkle root exists, matches this package and version, * and has the same checksum as the one we calculated. * * @param InstallFile $file * @return bool */ public function verifyMerkleRoot(InstallFile $file) : bool { $debugArgs = ['supplier' => $this->supplier->getName(), 'name' => $this->package]; $db = \Airship\get_database(); $merkle = $db->row('SELECT * FROM airship_tree_updates WHERE merkleroot = ?', $file->getMerkleRoot()); if (empty($merkle)) { $this->log('Merkle root not found in tree', LogLevel::DEBUG, $debugArgs); // Not found in Keyggdrasil return false; } $data = \Airship\parseJSON($merkle['data'], true); $instType = \strtolower($this->type); $keyggdrasilType = \strtolower($data['pkg_type']); if (!\hash_equals($instType, $keyggdrasilType)) { $this->log('Wrong package type', LogLevel::DEBUG, $debugArgs); // Wrong package type return false; } if (!\hash_equals($this->supplier->getName(), $data['supplier'])) { $this->log('Wrong supplier', LogLevel::DEBUG, $debugArgs); // Wrong supplier return false; } if (!\hash_equals($this->package, $data['name'])) { $this->log('Wrong package', LogLevel::DEBUG, $debugArgs); // Wrong package return false; } // Finally, we verify that the checksum matches the entry in our Merkle tree: return \hash_equals($file->getHash(), $data['checksum']); }
/** * Check that the signature is valid for this supplier's * public keys. * * @param bool $fastExit * @return bool */ public function signatureIsValid(bool $fastExit = false) : bool { $result = false; foreach ($this->supplier->getSigningKeys() as $key) { $result = $result || File::verify($this->path, $key['key'], $this->releaseInfo['signature']); if ($result && $fastExit) { return true; } } return $result; }
/** * Verify the Ed25519 signature of the update file against the * supplier's public key. * * Dear future security auditors: This is important. * * @param UpdateInfo $info * @param UpdateFile $file * @return bool */ public function verifyUpdateSignature(UpdateInfo $info, UpdateFile $file) : bool { $debugArgs = ['path' => $file->getPath(), 'supplier' => $info->getSupplierName(), 'name' => $info->getPackageName()]; $this->log('Checking update signature...', LogLevel::DEBUG, $debugArgs); $ret = false; foreach ($this->supplier->getSigningKeys() as $key) { if ($key['type'] !== 'signing') { continue; } $ret = $ret || File::verify($file->getPath(), $key['key'], $info->getSignature(true)); } $this->log('Signature result: ' . ($ret ? 'true' : 'false'), LogLevel::DEBUG, $debugArgs); return $ret; }