1 /*
2  * Copyright (C) 2021 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 package com.android.server.uwb.secure.csml;
17 
18 import static com.android.server.uwb.secure.iso7816.Iso7816Constants.CLA_PROPRIETARY;
19 
20 import android.annotation.NonNull;
21 
22 import com.android.server.uwb.secure.iso7816.CommandApdu;
23 import com.android.server.uwb.secure.iso7816.StatusWord;
24 import com.android.server.uwb.secure.iso7816.TlvDatum;
25 import com.android.server.uwb.secure.iso7816.TlvDatum.Tag;
26 
27 import java.io.ByteArrayOutputStream;
28 import java.io.DataOutputStream;
29 import java.io.IOException;
30 import java.util.List;
31 
32 /**
33  * The base class of all C-APDU defined by FiRa.
34  */
35 public abstract class FiRaCommand {
36     public static final Tag FIRA_PROPRIETARY_COMMAND_TEMP_TAG =
37             new Tag((byte) 0x71);
38 
FiRaCommand()39     protected FiRaCommand(){
40     }
41 
getCla()42     protected byte getCla() {
43         // logical channel number is not available. Use the default value.
44         return CLA_PROPRIETARY;
45     }
46 
getIns()47     protected abstract byte getIns();
48 
getP1()49     protected byte getP1() {
50         return (byte) 0x00;
51     }
52 
getP2()53     protected byte getP2() {
54         return (byte) 0x00;
55     }
56 
getLe()57     protected byte getLe() {
58         return (byte) 0x00;
59     }
60 
getExpectedSw()61     protected abstract StatusWord[] getExpectedSw();
62 
63     @NonNull
getTlvPayload()64     protected abstract List<TlvDatum> getTlvPayload();
65 
66     @NonNull
buildPayload(@onNull List<TlvDatum> tlvData)67     private byte[] buildPayload(@NonNull List<TlvDatum> tlvData) {
68         if (tlvData.size() == 0) {
69             return new byte[0];
70         }
71         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
72         DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
73         try {
74             for (TlvDatum tlv : tlvData) {
75                 dataOutputStream.write(tlv.toBytes());
76             }
77 
78             dataOutputStream.flush();
79         } catch (IOException e) {
80             return new byte[0];
81         }
82         return byteArrayOutputStream.toByteArray();
83     }
84 
85     /**
86      * Converts the FiRa command to the CommandApdu of ISO7816-4.
87      */
88     @NonNull
getCommandApdu()89     public CommandApdu getCommandApdu() {
90         CommandApdu commandApdu = CommandApdu.builder(getCla(), getIns(), getP1(), getP2())
91                 .setCdata(buildPayload(getTlvPayload()))
92                 .setLe(getLe())
93                 .setExpected(getExpectedSw())
94                 .build();
95         return commandApdu;
96     }
97 }
98