// --- BEGIN COPYRIGHT BLOCK --- // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301 USA // // Copyright (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- #include #include "apdu/APDU.h" #include "engine/RA.h" #include "main/Util.h" #include "main/Memory.h" #ifdef XP_WIN32 #define TPS_PUBLIC __declspec(dllexport) #else /* !XP_WIN32 */ #define TPS_PUBLIC #endif /* !XP_WIN32 */ /** * Constructs an APDU. * * ============== * APDU: * APDU are commands that can be sent from an authorized entity * (such as RA) to the token. It takes the following form: * --------------------------------------------------- * | CLA | INS | P1 | P2 | lc | data... * --------------------------------------------------- * * The values for the APDU header: CLA, INS, P1, P2 and lc are defined * in each individual APDU class. * * ============== * Status Words (response): * When APDUs are sent to the token, a response is returned. The following * is a list of all possible Return Codes (Status Words): * * * * ============== * ObjectID: * byte[0] - an ASCII letter, * 'c' - An object containing PKCS11 attributes for a certificate * 'k' - An object containing PKCS11 attributes for a public or private key * 'r' - An object containing PKCS11 attributes for a "reader" * 8 and not divisible by 8 pad_needed = 8 - (data_to_enc.size() % 8); } if (pad_needed) { // RA::Debug(LL_ALL_DATA_IN_PDU, "APDU::SecureMessage", "padding needed =%d", pad_needed); data_to_enc += Buffer(1, 0x80); pad_needed --; if (pad_needed) { // RA::Debug(LL_ALL_DATA_IN_PDU, "APDU::SecureMessage", "padding needed =%d", pad_needed); padding = Buffer(pad_needed, (BYTE)0); for (int i = 0; i < pad_needed; i++) { ((BYTE*)padding)[i] = 0x00; } /* for */ } // pad needed } else { // RA::Debug(LL_ALL_DATA_IN_PDU, "APDU::SecureMessage", "padding not needed"); } if (padding.size() > 0) { data_to_enc += Buffer(padding, padding.size()); } #ifdef ENC_DEBUG // RA::DebugBuffer("APDU::SecureMessage", "data to encrypt (post padding)= ",&data_to_enc); #endif // now, encrypt "data_to_enc" rv = Util::EncryptData(encSessionKey, data_to_enc, data_encrypted); if (rv == PR_FAILURE) { // RA::Error("APDU::SecureMessage", "encryption failed"); goto done; } else { // RA::Debug(LL_PER_PDU, "APDU::SecureMessage", "encryption succeeded"); // RA::Debug(LL_PER_PDU, "APDU::SecureMessage", "encrypted data length = %d", // data_encrypted.size()); // set "m_data" m_data = data_encrypted; } // lc should be automatically set correctly when getEncoding is called done: return rv; } /** * Retrieves APDU's encoding. * The encoding of APDU is as follows: * * CLA 1 byte * INS 1 byte * P1 1 byte * P2 1 byte * 1 byte * byte(s) * 0 1 byte * * @param data the result buffer which will contain the actual data * including the APDU header, data, and pre-calculated mac. */ TPS_PUBLIC void APDU::GetEncoding(Buffer &data) { data += Buffer(1, m_cla); data += Buffer(1, m_ins); data += Buffer(1, m_p1); data += Buffer(1, m_p2); data += Buffer(1, (BYTE)m_data.size() + m_mac.size()); data += Buffer(m_data, m_data.size()); if (m_mac.size() > 0) { data += Buffer(m_mac, m_mac.size()); } } /* Encode */