1 /*
2  * Copyright (C) 2017 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  * Copyright (c) 2015-2017, The Linux Foundation.
18  */
19 /*
20  * Copyright 2013 Giesecke & Devrient GmbH.
21  *
22  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
23  * use this file except in compliance with the License. You may obtain a copy of
24  * the License at
25  *
26  * http://www.apache.org/licenses/LICENSE-2.0
27  *
28  * Unless required by applicable law or agreed to in writing, software
29  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
30  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
31  * License for the specific language governing permissions and limitations under
32  * the License.
33  */
34 
35 package com.android.se.internal;
36 
37 /** Utilities class. */
38 public final class ByteArrayConverter {
39 
40     /** Override the default constructor to make it private. */
ByteArrayConverter()41     private ByteArrayConverter() {
42     }
43 
44     /**
45      * Forms a FileViewProvider-compatible path String (i.e., transforms the byte array {0x3F, 0x00,
46      * 0x2F, 0xE2} into the String "3F00:2FE2").
47      *
48      * @param rawPath The byte array containing the path component.
49      * @return A FileViewProvider-compatible path String.
50      * @throws IllegalArgumentException if the path has a bad coding.
51      */
byteArrayToPathString(byte[] rawPath)52     public static String byteArrayToPathString(byte[] rawPath) throws IllegalArgumentException {
53         if (rawPath.length % 2 != 0) {
54             throw new IllegalArgumentException("Invald path");
55         }
56 
57         byte[] buffer = new byte[2];
58         String path = "";
59         for (int i = 0; i < rawPath.length; i += 2) {
60             System.arraycopy(rawPath, i, buffer, 0, 2);
61             String fid = byteArrayToHexString(buffer);
62             if (fid.equalsIgnoreCase("3F00")) {
63                 // MF should not be included in path
64                 continue;
65             }
66             path = path.concat(fid);
67             if (i != rawPath.length - 2) {
68                 path = path.concat(":");
69             }
70         }
71         return path;
72     }
73 
74     /**
75      * Forms an hex-encoded String of the specified byte array.
76      *
77      * @param array  The byte array to be hex-encoded.
78      * @param offset The start position.
79      * @param length The number of bytes to be converted.
80      * @return A hex-encoded String of the specified byte array.
81      */
byteArrayToHexString(byte[] array, int offset, int length)82     public static String byteArrayToHexString(byte[] array, int offset, int length) {
83         if (array == null) {
84             return "";
85         }
86 
87         StringBuilder sb = new StringBuilder();
88 
89         for (int i = 0; i < length; i++) {
90             sb.append(String.format("%02x", array[offset + i] & 0xFF));
91         }
92 
93         return sb.toString();
94     }
95 
96     /** Converts the byte array to Hex String from a given offset */
byteArrayToHexString(byte[] array, int offset)97     public static String byteArrayToHexString(byte[] array, int offset) {
98         StringBuffer s = new StringBuffer();
99         for (int i = offset; i < array.length; i++) {
100             s.append(Integer.toHexString(0x100 + (array[i] & 0xff)).substring(1));
101         }
102         return s.toString();
103     }
104 
105     /**
106      * Forms an hex-encoded String of the specified byte array.
107      *
108      * @param byteArray The byte array to be hex-encoded.
109      * @return A hex-encoded String of the specified byte array.
110      */
byteArrayToHexString(byte[] byteArray)111     public static String byteArrayToHexString(byte[] byteArray) {
112         if (byteArray == null) {
113             return "";
114         }
115         return byteArrayToHexString(byteArray, 0, byteArray.length);
116     }
117 
118     /**
119      * Forms a byte array containing the values of the hex-encoded string.
120      *
121      * @param str    The hex-encoded string to be converted to byte-array.
122      * @param offset The start position.
123      * @param length The number of chars to be converted (must be multiple of 2).
124      * @return A byte array containing the values of the hex-encoded string.
125      */
hexStringToByteArray(String str, int offset, int length)126     public static byte[] hexStringToByteArray(String str, int offset, int length) {
127         if (length % 2 != 0) {
128             throw new IllegalArgumentException("length must be multiple of 2");
129         }
130 
131         str = str.toUpperCase();
132 
133         byte[] outputBytes = new byte[str.length() / 2];
134 
135         for (int i = 0; i < length; i += 2) {
136             char c1 = str.charAt(i + offset);
137             char c2 = str.charAt(i + 1 + offset);
138             if (!isHexChar(c1) || !isHexChar(c2)) {
139                 throw new IllegalArgumentException("Invalid char found");
140             }
141 
142             outputBytes[i / 2] = (byte) ((Character.digit(c1, 16) << 4) + Character.digit(c2, 16));
143         }
144 
145         return outputBytes;
146     }
147 
148     /**
149      * Forms a byte array containing the values of the hex-encoded string.
150      *
151      * @param str The hex-encoded string to be converted to byte-array.
152      * @return A byte array containing the values of the hex-encoded string.
153      */
hexStringToByteArray(String str)154     public static byte[] hexStringToByteArray(String str) {
155         return hexStringToByteArray(str, 0, str.length());
156     }
157 
158     /**
159      * Forms a byte array containing the specified integer value.
160      *
161      * @param value The integer value to be converted to byte array.
162      * @return A byte array containing the specified integer value.
163      */
intToByteArray(int value)164     public static byte[] intToByteArray(int value) {
165         return new byte[]{
166                 (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value
167         };
168     }
169 
170     /**
171      * Forms an integer from a byte array.
172      *
173      * @param byteArray The byte array from where to form the integer.
174      * @return The integer value representing the specified byte array. 0 if the array is empty. If
175      * the array is longer than 4 bytes, only bytes 0 to 3 will be considered.
176      */
byteArrayToInt(byte[] byteArray)177     public static int byteArrayToInt(byte[] byteArray) {
178         switch (byteArray.length) {
179             case 0:
180                 return 0;
181             case 1:
182                 return (byteArray[0] & 0xFF);
183             case 2:
184                 return (byteArray[0] & 0xFF) << 8 | (byteArray[1] & 0xFF);
185             case 3:
186                 return (byteArray[0] & 0xFF) << 16 | (byteArray[1] & 0xFF) << 8 | (byteArray[2]
187                         & 0xFF);
188             default:
189                 return (byteArray[0] & 0xFF) << 24
190                         | (byteArray[1] & 0xFF) << 16
191                         | (byteArray[2] & 0xFF) << 8
192                         | byteArray[3] & 0xFF;
193         }
194     }
195 
196     /**
197      * Decides whether a char is a valid hex value or not.
198      *
199      * @param c The char to be evaluated.
200      * @return true if the specified char is a valid hex value, false otherwise.
201      */
isHexChar(char c)202     public static boolean isHexChar(char c) {
203         if (Character.isLowerCase(c)) {
204             c = Character.toUpperCase(c);
205         }
206 
207         return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F');
208     }
209 }
210