1 /* 2 * Copyright (C) 2023 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.nearby.presence; 18 19 import android.annotation.IntDef; 20 import android.annotation.Nullable; 21 import android.nearby.DataElement; 22 23 import androidx.annotation.NonNull; 24 25 import com.android.internal.util.Preconditions; 26 import com.android.server.nearby.util.ArrayUtils; 27 28 import java.util.Arrays; 29 30 /** 31 * Data Element that indicates the presence of extended 16 bytes salt instead of 2 byte salt and to 32 * indicate which encoding scheme (MIC tag or Signature) is used for a section. If present, it must 33 * be the first DE in a section. 34 */ 35 public class EncryptionInfo { 36 37 @IntDef({EncodingScheme.MIC, EncodingScheme.SIGNATURE}) 38 public @interface EncodingScheme { 39 int MIC = 0; 40 int SIGNATURE = 1; 41 } 42 43 // 1st byte : encryption scheme 44 // 2nd to 17th bytes: salt 45 public static final int ENCRYPTION_INFO_LENGTH = 17; 46 private static final int ENCODING_SCHEME_MASK = 0b01111000; 47 private static final int ENCODING_SCHEME_OFFSET = 3; 48 @EncodingScheme 49 private final int mEncodingScheme; 50 private final byte[] mSalt; 51 52 /** 53 * Constructs a {@link DataElement}. 54 */ EncryptionInfo(@onNull byte[] value)55 public EncryptionInfo(@NonNull byte[] value) { 56 Preconditions.checkArgument(value.length == ENCRYPTION_INFO_LENGTH); 57 mEncodingScheme = (value[0] & ENCODING_SCHEME_MASK) >> ENCODING_SCHEME_OFFSET; 58 Preconditions.checkArgument(isValidEncodingScheme(mEncodingScheme)); 59 mSalt = Arrays.copyOfRange(value, 1, ENCRYPTION_INFO_LENGTH); 60 } 61 isValidEncodingScheme(int scheme)62 private boolean isValidEncodingScheme(int scheme) { 63 return scheme == EncodingScheme.MIC || scheme == EncodingScheme.SIGNATURE; 64 } 65 66 @EncodingScheme getEncodingScheme()67 public int getEncodingScheme() { 68 return mEncodingScheme; 69 } 70 getSalt()71 public byte[] getSalt() { 72 return mSalt; 73 } 74 75 /** Combines the encoding scheme and salt to a byte array 76 * that represents an {@link EncryptionInfo}. 77 */ 78 @Nullable toByte(@ncodingScheme int encodingScheme, byte[] salt)79 public static byte[] toByte(@EncodingScheme int encodingScheme, byte[] salt) { 80 if (ArrayUtils.isEmpty(salt)) { 81 return null; 82 } 83 if (salt.length != ENCRYPTION_INFO_LENGTH - 1) { 84 return null; 85 } 86 byte schemeByte = 87 (byte) ((encodingScheme << ENCODING_SCHEME_OFFSET) & ENCODING_SCHEME_MASK); 88 return ArrayUtils.append(schemeByte, salt); 89 } 90 } 91