10aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root/*
20aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * Copyright (C) 2011 The Android Open Source Project
30aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root *
40aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
50aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * you may not use this file except in compliance with the License.
60aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * You may obtain a copy of the License at
70aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root *
80aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
90aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root *
100aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * Unless required by applicable law or agreed to in writing, software
110aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
120aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * See the License for the specific language governing permissions and
140aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * limitations under the License.
150aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root */
160aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
170aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootpackage android.content.pm;
180aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
190aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootimport android.os.Parcel;
200aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootimport android.os.Parcelable;
210aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
220aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootimport java.io.UnsupportedEncodingException;
230aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootimport java.security.SecureRandom;
240aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootimport java.util.Random;
250aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
260aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root/**
270aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * An identity that uniquely identifies a particular device. In this
280aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * implementation, the identity is represented as a 64-bit integer encoded to a
290aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * 13-character string using RFC 4648's Base32 encoding without the trailing
300aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * padding. This makes it easy for users to read and write the code without
310aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * confusing 'I' (letter) with '1' (one) or 'O' (letter) with '0' (zero).
320aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root *
330aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root * @hide
340aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root */
350aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootpublic class VerifierDeviceIdentity implements Parcelable {
360aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    /**
370aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * Encoded size of a long (64-bit) into Base32. This format will end up
380aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * looking like XXXX-XXXX-XXXX-X (length ignores hyphens) when applied with
390aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * the GROUP_SIZE below.
400aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     */
410aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private static final int LONG_SIZE = 13;
420aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
430aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    /**
440aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * Size of groupings when outputting as strings. This helps people read it
450aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * out and keep track of where they are.
460aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     */
470aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private static final int GROUP_SIZE = 4;
480aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
490aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private final long mIdentity;
500aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
510aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private final String mIdentityString;
520aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
530aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    /**
540aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * Create a verifier device identity from a long.
550aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     *
560aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * @param identity device identity in a 64-bit integer.
570aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * @throws
580aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     */
590aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public VerifierDeviceIdentity(long identity) {
600aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        mIdentity = identity;
610aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        mIdentityString = encodeBase32(identity);
620aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
630aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
640aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private VerifierDeviceIdentity(Parcel source) {
650aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        final long identity = source.readLong();
660aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
670aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        mIdentity = identity;
680aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        mIdentityString = encodeBase32(identity);
690aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
700aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
710aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    /**
720aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * Generate a new device identity.
730aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     *
740aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * @return random uniformly-distributed device identity
750aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     */
760aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public static VerifierDeviceIdentity generate() {
770aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        final SecureRandom sr = new SecureRandom();
780aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return generate(sr);
790aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
800aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
810aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    /**
820aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * Generate a new device identity using a provided random number generator
830aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * class. This is used for testing.
840aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     *
850aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * @param rng random number generator to retrieve the next long from
860aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     * @return verifier device identity based on the input from the provided
870aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     *         random number generator
880aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root     */
890aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    static VerifierDeviceIdentity generate(Random rng) {
900aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        long identity = rng.nextLong();
910aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return new VerifierDeviceIdentity(identity);
920aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
930aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
940aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private static final char ENCODE[] = {
950aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
960aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
970aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
980aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        'Y', 'Z', '2', '3', '4', '5', '6', '7',
990aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    };
1000aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1010aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private static final char SEPARATOR = '-';
1020aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1030aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private static final String encodeBase32(long input) {
1040aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        final char[] alphabet = ENCODE;
1050aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1060aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        /*
1070aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root         * Make a character array with room for the separators between each
1080aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root         * group.
1090aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root         */
1100aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        final char encoded[] = new char[LONG_SIZE + (LONG_SIZE / GROUP_SIZE)];
1110aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1120aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        int index = encoded.length;
1130aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        for (int i = 0; i < LONG_SIZE; i++) {
1140aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            /*
1150aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             * Make sure we don't put a separator at the beginning. Since we're
1160aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             * building from the rear of the array, we use (LONG_SIZE %
1170aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             * GROUP_SIZE) to make the odd-size group appear at the end instead
1180aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             * of the beginning.
1190aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             */
1200aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            if (i > 0 && (i % GROUP_SIZE) == (LONG_SIZE % GROUP_SIZE)) {
1210aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                encoded[--index] = SEPARATOR;
1220aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            }
1230aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1240aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            /*
1250aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             * Extract 5 bits of data, then shift it out.
1260aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             */
1270aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            final int group = (int) (input & 0x1F);
1280aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            input >>>= 5;
1290aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1300aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            encoded[--index] = alphabet[group];
1310aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        }
1320aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1330aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return String.valueOf(encoded);
1340aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
1350aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1360aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    // TODO move this out to its own class (android.util.Base32)
1370aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    private static final long decodeBase32(byte[] input) throws IllegalArgumentException {
1380aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        long output = 0L;
1390aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        int numParsed = 0;
1400aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1410aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        final int N = input.length;
1420aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        for (int i = 0; i < N; i++) {
1430aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            final int group = input[i];
1440aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1450aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            /*
1460aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             * This essentially does the reverse of the ENCODED alphabet above
1470aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             * without a table. A..Z are 0..25 and 2..7 are 26..31.
1480aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root             */
1490aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            final int value;
1500aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            if ('A' <= group && group <= 'Z') {
1510aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                value = group - 'A';
1520aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            } else if ('2' <= group && group <= '7') {
1530aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                value = group - ('2' - 26);
1540aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            } else if (group == SEPARATOR) {
1550aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                continue;
156a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root            } else if ('a' <= group && group <= 'z') {
157a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root                /* Lowercase letters should be the same as uppercase for Base32 */
158a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root                value = group - 'a';
159a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root            } else if (group == '0') {
160a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root                /* Be nice to users that mistake O (letter) for 0 (zero) */
161a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root                value = 'O' - 'A';
162a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root            } else if (group == '1') {
163a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root                /* Be nice to users that mistake I (letter) for 1 (one) */
164a0f264e1afa3c0a00a5af0db362f884b122d978dKenny Root                value = 'I' - 'A';
1650aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            } else {
1660aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                throw new IllegalArgumentException("base base-32 character: " + group);
1670aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            }
1680aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1690aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            output = (output << 5) | value;
1700aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            numParsed++;
1710aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1720aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            if (numParsed == 1) {
1730aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                if ((value & 0xF) != value) {
1740aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                    throw new IllegalArgumentException("illegal start character; will overflow");
1750aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                }
1760aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            } else if (numParsed > 13) {
1770aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root                throw new IllegalArgumentException("too long; should have 13 characters");
1780aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            }
1790aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        }
1800aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1810aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        if (numParsed != 13) {
1820aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            throw new IllegalArgumentException("too short; should have 13 characters");
1830aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        }
1840aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1850aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return output;
1860aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
1870aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1880aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    @Override
1890aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public int hashCode() {
1900aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return (int) mIdentity;
1910aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
1920aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1930aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    @Override
1940aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public boolean equals(Object other) {
1950aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        if (!(other instanceof VerifierDeviceIdentity)) {
1960aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            return false;
1970aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        }
1980aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
1990aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        final VerifierDeviceIdentity o = (VerifierDeviceIdentity) other;
2000aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return mIdentity == o.mIdentity;
2010aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
2020aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
2030aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    @Override
2040aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public String toString() {
2050aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return mIdentityString;
2060aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
2070aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
2080aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public static VerifierDeviceIdentity parse(String deviceIdentity)
2090aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            throws IllegalArgumentException {
2100aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        final byte[] input;
2110aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        try {
2120aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            input = deviceIdentity.getBytes("US-ASCII");
2130aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        } catch (UnsupportedEncodingException e) {
2140aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            throw new IllegalArgumentException("bad base-32 characters in input");
2150aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        }
2160aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
2170aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return new VerifierDeviceIdentity(decodeBase32(input));
2180aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
2190aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
2200aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    @Override
2210aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public int describeContents() {
2220aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        return 0;
2230aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
2240aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
2250aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    @Override
2260aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public void writeToParcel(Parcel dest, int flags) {
2270aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        dest.writeLong(mIdentity);
2280aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    }
2290aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
2300aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    public static final Parcelable.Creator<VerifierDeviceIdentity> CREATOR
2310aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            = new Parcelable.Creator<VerifierDeviceIdentity>() {
2320aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        public VerifierDeviceIdentity createFromParcel(Parcel source) {
2330aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            return new VerifierDeviceIdentity(source);
2340aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        }
2350aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root
2360aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        public VerifierDeviceIdentity[] newArray(int size) {
2370aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root            return new VerifierDeviceIdentity[size];
2380aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root        }
2390aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root    };
2400aaa0d931716e9f57a1d84d795fab2df75092756Kenny Root}
241