• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 *
18 *  The original Work has been changed by NXP.
19 *
20 *  Licensed under the Apache License, Version 2.0 (the "License");
21 *  you may not use this file except in compliance with the License.
22 *  You may obtain a copy of the License at
23 *
24 *  http://www.apache.org/licenses/LICENSE-2.0
25 *
26 *  Unless required by applicable law or agreed to in writing, software
27 *  distributed under the License is distributed on an "AS IS" BASIS,
28 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 *  See the License for the specific language governing permissions and
30 *  limitations under the License.
31 *
32 *  Copyright 2022-2023 NXP
33 *
34 ******************************************************************************/
35 #pragma once
36 
37 #include <ITransport.h>
38 #include "CborConverter.h"
39 
40 #define APDU_CLS 0x80
41 //#define APDU_P1 0x50
42 #define APDU_P1 0x60
43 #define APDU_P2 0x00
44 #define APDU_RESP_STATUS_OK 0x9000
45 
46 #define KEYMINT_CMD_APDU_START 0x20
47 
48 #define KEYMINT_VENDOR_CMD_APDU_START 0xD0
49 
50 namespace keymint::javacard {
51 using std::shared_ptr;
52 using std::vector;
53 
54 enum class Instruction {
55     // Keymaster commands
56     INS_GENERATE_KEY_CMD = KEYMINT_CMD_APDU_START + 1,
57     INS_IMPORT_KEY_CMD = KEYMINT_CMD_APDU_START + 2,
58     INS_IMPORT_WRAPPED_KEY_CMD = KEYMINT_CMD_APDU_START + 3,
59     INS_EXPORT_KEY_CMD = KEYMINT_CMD_APDU_START + 4,
60     INS_ATTEST_KEY_CMD = KEYMINT_CMD_APDU_START + 5,
61     INS_UPGRADE_KEY_CMD = KEYMINT_CMD_APDU_START + 6,
62     INS_DELETE_KEY_CMD = KEYMINT_CMD_APDU_START + 7,
63     INS_DELETE_ALL_KEYS_CMD = KEYMINT_CMD_APDU_START + 8,
64     INS_ADD_RNG_ENTROPY_CMD = KEYMINT_CMD_APDU_START + 9,
65     INS_COMPUTE_SHARED_SECRET_CMD = KEYMINT_CMD_APDU_START + 10,
66     INS_DESTROY_ATT_IDS_CMD = KEYMINT_CMD_APDU_START + 11,
67     INS_VERIFY_AUTHORIZATION_CMD = KEYMINT_CMD_APDU_START + 12,
68     INS_GET_SHARED_SECRET_PARAM_CMD = KEYMINT_CMD_APDU_START + 13,
69     INS_GET_KEY_CHARACTERISTICS_CMD = KEYMINT_CMD_APDU_START + 14,
70     INS_GET_HW_INFO_CMD = KEYMINT_CMD_APDU_START + 15,
71     INS_BEGIN_OPERATION_CMD = KEYMINT_CMD_APDU_START + 16,
72     INS_UPDATE_OPERATION_CMD = KEYMINT_CMD_APDU_START + 17,
73     INS_FINISH_OPERATION_CMD = KEYMINT_CMD_APDU_START + 18,
74     INS_ABORT_OPERATION_CMD = KEYMINT_CMD_APDU_START + 19,
75     INS_DEVICE_LOCKED_CMD = KEYMINT_CMD_APDU_START + 20,
76     INS_EARLY_BOOT_ENDED_CMD = KEYMINT_CMD_APDU_START + 21,
77     INS_GET_CERT_CHAIN_CMD = KEYMINT_CMD_APDU_START + 22,
78     INS_UPDATE_AAD_OPERATION_CMD = KEYMINT_CMD_APDU_START + 23,
79     INS_BEGIN_IMPORT_WRAPPED_KEY_CMD = KEYMINT_CMD_APDU_START + 24,
80     INS_FINISH_IMPORT_WRAPPED_KEY_CMD = KEYMINT_CMD_APDU_START + 25,
81     //INS_INIT_STRONGBOX_CMD = KEYMINT_CMD_APDU_START + 26,
82     INS_INIT_STRONGBOX_CMD = KEYMINT_VENDOR_CMD_APDU_START + 9,
83     // RKP Commands
84     INS_GET_RKP_HARDWARE_INFO = KEYMINT_CMD_APDU_START + 27,
85     INS_GENERATE_RKP_KEY_CMD = KEYMINT_CMD_APDU_START + 28,
86     INS_BEGIN_SEND_DATA_CMD = KEYMINT_CMD_APDU_START + 29,
87     INS_UPDATE_KEY_CMD = KEYMINT_CMD_APDU_START + 30,
88     INS_UPDATE_EEK_CHAIN_CMD = KEYMINT_CMD_APDU_START + 31,
89     INS_UPDATE_CHALLENGE_CMD = KEYMINT_CMD_APDU_START + 32,
90     INS_FINISH_SEND_DATA_CMD = KEYMINT_CMD_APDU_START + 33,
91     INS_GET_RESPONSE_CMD = KEYMINT_CMD_APDU_START + 34,
92     INS_GET_UDS_CERTS_CMD = KEYMINT_CMD_APDU_START + 35,
93     INS_GET_DICE_CERT_CHAIN_CMD = KEYMINT_CMD_APDU_START + 36,
94     // SE ROT Commands
95     INS_GET_ROT_CHALLENGE_CMD = KEYMINT_CMD_APDU_START + 45,
96     INS_GET_ROT_DATA_CMD = KEYMINT_CMD_APDU_START + 46,
97     INS_SEND_ROT_DATA_CMD = KEYMINT_CMD_APDU_START + 47,
98 };
99 
100 class JavacardSecureElement {
101   public:
JavacardSecureElement(shared_ptr<ITransport> transport)102     explicit JavacardSecureElement(shared_ptr<ITransport> transport)
103         : transport_(std::move(transport)), isEarlyBootEndedPending(false),
104           isDeleteAllKeysPending(false) {
105       transport_->openConnection();
106     }
~JavacardSecureElement()107     virtual ~JavacardSecureElement() { transport_->closeConnection(); }
108 
109     std::tuple<std::unique_ptr<Item>, keymaster_error_t> sendRequest(Instruction ins,
110                                                                      Array& request);
111     std::tuple<std::unique_ptr<Item>, keymaster_error_t> sendRequest(Instruction ins);
112     std::tuple<std::unique_ptr<Item>, keymaster_error_t> sendRequest(Instruction ins,
113                                                                      std::vector<uint8_t>& command);
114 
115     keymaster_error_t sendData(Instruction ins, std::vector<uint8_t>& inData,
116                                std::vector<uint8_t>& response);
117 
118     keymaster_error_t constructApduMessage(Instruction& ins, std::vector<uint8_t>& inputData,
119                                            std::vector<uint8_t>& apduOut);
120     keymaster_error_t initializeJavacard();
121     void sendPendingEvents();
122     void setEarlyBootEndedPending();
123     void setDeleteAllKeysPending();
124 
getApduStatus(std::vector<uint8_t> & inputData)125     inline uint16_t getApduStatus(std::vector<uint8_t>& inputData) {
126         // Last two bytes are the status SW0SW1
127         uint8_t SW0 = inputData.at(inputData.size() - 2);
128         uint8_t SW1 = inputData.at(inputData.size() - 1);
129         return (SW0 << 8 | SW1);
130     }
131 
132   private:
133     shared_ptr<ITransport> transport_;
134     bool isEarlyBootEndedPending;
135     bool isDeleteAllKeysPending;
136     CborConverter cbor_;
137 };
138 }  // namespace keymint::javacard
139