1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.biometrics;
18 
19 import static java.nio.ByteOrder.LITTLE_ENDIAN;
20 
21 import android.hardware.keymaster.HardwareAuthToken;
22 import android.hardware.keymaster.Timestamp;
23 
24 import java.nio.ByteOrder;
25 
26 /**
27  * Utilities for converting between old and new HardwareAuthToken types. See
28  * {@link HardwareAuthToken}.
29  */
30 public class HardwareAuthTokenUtils {
toByteArray(HardwareAuthToken hat)31     public static byte[] toByteArray(HardwareAuthToken hat) {
32         final byte[] array = new byte[69];
33 
34         // Version, first byte. Used in hw_auth_token.h but not HardwareAuthToken
35         array[0] = 0;
36 
37         // Challenge, 1:8.
38         writeLong(hat.challenge, array, 1 /* offset */);
39 
40         // UserId, 9:16.
41         writeLong(hat.userId, array, 9 /* offset */);
42 
43         // AuthenticatorId, 17:24.
44         writeLong(hat.authenticatorId, array, 17 /* offset */);
45 
46         // AuthenticatorType, 25:28.
47         writeInt(flipIfNativelyLittle(hat.authenticatorType), array, 25 /* offset */);
48 
49         // Timestamp, 29:36.
50         writeLong(flipIfNativelyLittle(hat.timestamp.milliSeconds), array, 29 /* offset */);
51 
52         // MAC, 37:69. Byte array.
53         System.arraycopy(hat.mac, 0 /* srcPos */, array, 37 /* destPos */, hat.mac.length);
54 
55         return array;
56     }
57 
toHardwareAuthToken(byte[] array)58     public static HardwareAuthToken toHardwareAuthToken(byte[] array) {
59         final HardwareAuthToken hardwareAuthToken = new HardwareAuthToken();
60 
61         // First byte is version, which doesn't not exist in HardwareAuthToken anymore
62         // Next 8 bytes is the challenge.
63         hardwareAuthToken.challenge = getLong(array, 1 /* offset */);
64 
65         // Next 8 bytes is the userId
66         hardwareAuthToken.userId = getLong(array, 9 /* offset */);
67 
68         // Next 8 bytes is the authenticatorId.
69         hardwareAuthToken.authenticatorId = getLong(array, 17 /* offset */);
70 
71         // Next 4 bytes is the authenticatorType.
72         hardwareAuthToken.authenticatorType = flipIfNativelyLittle(getInt(array, 25 /* offset */));
73 
74         // Next 8 bytes is the timestamp.
75         final Timestamp timestamp = new Timestamp();
76         timestamp.milliSeconds = flipIfNativelyLittle(getLong(array, 29 /* offset */));
77         hardwareAuthToken.timestamp = timestamp;
78 
79         // Last 32 bytes is the mac, 37:69
80         hardwareAuthToken.mac = new byte[32];
81         System.arraycopy(array, 37 /* srcPos */,
82                 hardwareAuthToken.mac,
83                 0 /* destPos */,
84                 32 /* length */);
85 
86         return hardwareAuthToken;
87     }
88 
flipIfNativelyLittle(long l)89     private static long flipIfNativelyLittle(long l) {
90         if (LITTLE_ENDIAN == ByteOrder.nativeOrder()) {
91             return Long.reverseBytes(l);
92         }
93         return l;
94     }
95 
flipIfNativelyLittle(int i)96     private static int flipIfNativelyLittle(int i) {
97         if (LITTLE_ENDIAN == ByteOrder.nativeOrder()) {
98             return Integer.reverseBytes(i);
99         }
100         return i;
101     }
102 
writeLong(long l, byte[] dest, int offset)103     private static void writeLong(long l, byte[] dest, int offset) {
104         dest[offset + 0] = (byte) l;
105         dest[offset + 1] = (byte) (l >> 8);
106         dest[offset + 2] = (byte) (l >> 16);
107         dest[offset + 3] = (byte) (l >> 24);
108         dest[offset + 4] = (byte) (l >> 32);
109         dest[offset + 5] = (byte) (l >> 40);
110         dest[offset + 6] = (byte) (l >> 48);
111         dest[offset + 7] = (byte) (l >> 56);
112     }
113 
writeInt(int i, byte[] dest, int offset)114     private static void writeInt(int i, byte[] dest, int offset) {
115         dest[offset + 0] = (byte) i;
116         dest[offset + 1] = (byte) (i >> 8);
117         dest[offset + 2] = (byte) (i >> 16);
118         dest[offset + 3] = (byte) (i >> 24);
119     }
120 
getLong(byte[] array, int offset)121     private static long getLong(byte[] array, int offset) {
122         long result = 0;
123         // Lowest bit is LSB
124         for (int i = 0; i < 8; i++) {
125             result += (long) ((array[i + offset] & 0xffL) << (8 * i));
126         }
127         return result;
128     }
129 
getInt(byte[] array, int offset)130     private static int getInt(byte[] array, int offset) {
131         int result = 0;
132         // Lowest bit is LSB
133         for (int i = 0; i < 4; i++) {
134             result += (int) (((int) array[i + offset] & 0xff) << (8 * i));
135         }
136         return result;
137     }
138 }
139