1 /*
2  * Copyright (C) 2022 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.uwb.secure.csml;
18 
19 import android.annotation.NonNull;
20 
21 import com.android.server.uwb.params.TlvBuffer;
22 import com.android.server.uwb.params.TlvDecoderBuffer;
23 
24 import java.util.Optional;
25 
26 /**
27  * The UWB session Key information in {@link SessionData}.
28  * See FiRa CSML 1.0 Table 53 - SECURE_RANGING_INFO
29  */
30 class SecureRangingInfo {
31     public static final int SECURE_RANGING_INFO_TAG = 0xA5;
32     public static final int UWB_SESSION_KEY_INFO_TAG = 0x80;
33     public static final int RESPONDER_SPECIFIC_SUB_SESSION_KEY_INFO_TAG = 0x81;
34     public static final int SUS_ADDITIONAL_PARAMS_TAG = 0x82;
35 
36     private static final int MAX_FIELD_COUNT = 3;
37 
38     public final Optional<byte[]> uwbSessionKeyInfo;
39     public final Optional<byte[]> uwbSubSessionKeyInfo;
40     public final Optional<byte[]> susAdditionalParams;
41 
SecureRangingInfo( Optional<byte[]> uwbSessionKeyInfo, Optional<byte[]> uwbSubSessionKeyInfo, Optional<byte[]> susAdditionalParams)42     private SecureRangingInfo(
43             Optional<byte[]> uwbSessionKeyInfo,
44             Optional<byte[]> uwbSubSessionKeyInfo,
45             Optional<byte[]> susAdditionalParams) {
46         this.uwbSessionKeyInfo = uwbSessionKeyInfo;
47         this.uwbSubSessionKeyInfo = uwbSubSessionKeyInfo;
48         this.susAdditionalParams = susAdditionalParams;
49     }
50 
51     /** Converts the{@link SecureRangingInfo} as TLV data payload. */
52     @NonNull
toBytes()53     byte[] toBytes() {
54         TlvBuffer.Builder secureInfoBuilder = new TlvBuffer.Builder();
55         uwbSessionKeyInfo.ifPresent(bArray -> secureInfoBuilder.putByteArray(
56                 UWB_SESSION_KEY_INFO_TAG, bArray));
57         uwbSubSessionKeyInfo.ifPresent(bArray -> secureInfoBuilder.putByteArray(
58                 RESPONDER_SPECIFIC_SUB_SESSION_KEY_INFO_TAG, bArray));
59         susAdditionalParams.ifPresent(bArray -> secureInfoBuilder.putByteArray(
60                 SUS_ADDITIONAL_PARAMS_TAG, bArray));
61         return secureInfoBuilder.build().getByteArray();
62     }
63 
64     @NonNull
getByteArrayValue(TlvDecoderBuffer parsedTlvBuffer, int tag)65     private static Optional<byte[]> getByteArrayValue(TlvDecoderBuffer parsedTlvBuffer, int tag) {
66         try {
67             return Optional.of(parsedTlvBuffer.getByteArray(tag));
68         } catch (IllegalArgumentException e) {
69             return Optional.empty();
70         }
71     }
72 
73     /** Gets the {@link SecureRangingInfo} from the TLV data. */
74     @NonNull
fromBytes(@onNull byte[] bytes)75     static SecureRangingInfo fromBytes(@NonNull byte[] bytes) {
76         TlvDecoderBuffer secureInfoTlv = new TlvDecoderBuffer(bytes, MAX_FIELD_COUNT);
77 
78         secureInfoTlv.parse();
79 
80         return new SecureRangingInfo(
81                 getByteArrayValue(secureInfoTlv, UWB_SESSION_KEY_INFO_TAG),
82                 getByteArrayValue(secureInfoTlv, RESPONDER_SPECIFIC_SUB_SESSION_KEY_INFO_TAG),
83                 getByteArrayValue(secureInfoTlv, SUS_ADDITIONAL_PARAMS_TAG));
84     }
85 
86     /** The builder class of {@link SecureRangingInfo} */
87     static class Builder {
88         private  Optional<byte[]> mUwbSessionKeyInfo = Optional.empty();
89         private  Optional<byte[]> mUwbSubSessionKeyInfo = Optional.empty();
90         private  Optional<byte[]> mSusAdditionalParams = Optional.empty();
91 
92         @NonNull
setUwbSessionKeyInfo(@onNull byte[] uwbSessionKeyInfo)93         Builder setUwbSessionKeyInfo(@NonNull byte[] uwbSessionKeyInfo) {
94             mUwbSessionKeyInfo = Optional.of(uwbSessionKeyInfo);
95             return this;
96         }
97 
98         @NonNull
setUwbSubSessionKeyInfo(@onNull byte[] uwbSubSessionKeyInfo)99         Builder setUwbSubSessionKeyInfo(@NonNull byte[] uwbSubSessionKeyInfo) {
100             mUwbSubSessionKeyInfo = Optional.of(uwbSubSessionKeyInfo);
101             return this;
102         }
103 
104         @NonNull
setSusAdditionalParams(@onNull byte[] susAdditionalParams)105         Builder setSusAdditionalParams(@NonNull byte[] susAdditionalParams) {
106             mSusAdditionalParams = Optional.of(susAdditionalParams);
107             return this;
108         }
109 
110         @NonNull
build()111         SecureRangingInfo build() {
112             return new SecureRangingInfo(
113                     mUwbSessionKeyInfo, mUwbSubSessionKeyInfo, mSusAdditionalParams);
114         }
115     }
116 }
117