Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checksum Error while provisioning Android Lollipop

I get the message Couldn't use the admin app due to a checksum error. Contact your IT department when using the code below. Basically you have two Android Lollipop devices. One device is unprovisioned (Factory reset) and the other has this programming app on it. The programming app sends an NFC command to the unprovisioned device to tell it to start provisioning using the data you pass to it. There are three fields required (APK Location, APK file checksum, and package name) as per DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC.

The APK is getting downloaded. I'm checking my server logs and it's clearly coming from the device (AndroidDownloadManager is in the user agent).

According to DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM it is a SHA-1 checksum of the file. The checksum is not matching. I've tried many different formats of this checksum (hex, hex with spaces, uppercase/lowercase, base64, text) and I guess it's possible I missed a test.

Unfortunately, the Android Lollipop source is not yet available otherwise I would be checking there.

How do I fix this? Any thoughts?

public class ProvisionerActivity extends Activity implements CreateNdefMessageCallback {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        mNfcAdapter.setNdefPushMessageCallback(this, this);
    }

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        try {
            Properties p = new Properties();
            p.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, "com.example.deviceownertest");
            p.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION, "http://example.com/DeviceOwnerTest.apk");
            p.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM, "19138948d8a607617971af724ffd08dd7eab771b");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            OutputStream out = new ObjectOutputStream(bos);
            p.store(out, "");
            byte[] bytes = bos.toByteArray();

            NdefMessage msg = new NdefMessage(NdefRecord.createMime(DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, bytes));
            return msg;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Note: This is using the latest Android L Developer Preview. I guess it is entirely possible that this feature isn't finished yet. Update: Actual release acts this way too.


APK: https://storage.googleapis.com/randy/DeviceOwnerCheck.apk
Checksum: FRaAsqdPSjp9nC5hKIU/ElPv+e4
Result: Using this URL and this checksum gives an error and doesn't even get to the encrypt device screen.


I also posted two applications to GitHub. One sends the NFC data to provision. The other is just an app to check if the app is device admin or device owner. Hopefully someone finds this useful. You'll need to modify the URL and the checksum if you want to build DeviceOwnerCheck yourself.

like image 490
Randy Avatar asked Oct 22 '14 14:10

Randy


1 Answers

The hash code must be url safe. This converts and removes trailing padding

$ cat Something.apk | openssl dgst -binary -sha1 | openssl base64 | tr '+/' '-_' | tr -d '='
like image 97
Rob Avatar answered Sep 21 '22 11:09

Rob