You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
8.0 KiB
C

/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSUE_PCSC_USIM_H
#define SRSUE_PCSC_USIM_H
#include "srslte/common/common.h"
#include "srslte/common/log.h"
#include "srslte/common/security.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srsue/hdr/stack/upper/usim.h"
#include <string>
#include <winscard.h>
namespace srsue {
#define AKA_RAND_LEN 16
#define AKA_AUTN_LEN 16
#define AKA_AUTS_LEN 14
#define RES_MAX_LEN 16
#define MAC_LEN 8
#define IK_LEN 16
#define CK_LEN 16
#define AK_LEN 6
#define SQN_LEN 6
#define KEY_LEN 32
typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types_t;
static inline uint16_t to_uint16(const uint8_t* a)
{
return (a[0] << 8) | a[1];
}
class pcsc_usim : public usim_base
{
public:
pcsc_usim(srslte::log* log_);
~pcsc_usim();
int init(usim_args_t* args);
void stop();
// NAS interface
std::string get_imsi_str();
std::string get_imei_str();
bool get_imsi_vec(uint8_t* imsi_, uint32_t n);
bool get_imei_vec(uint8_t* imei_, uint32_t n);
bool get_home_plmn_id(srslte::plmn_id_t* home_plmn_id);
auth_result_t generate_authentication_response(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme);
void generate_nas_keys(uint8_t* k_asme,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
// RRC interface
void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg);
void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg);
void store_keys_before_ho(const srslte::as_security_config_t& as_ctx);
void restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx);
private:
srslte::log* log = nullptr;
// User data
// 3GPP 33.102 v10.0.0 Annex H
uint64_t imsi = 0;
uint64_t imei = 0;
std::string imsi_str;
std::string imei_str;
uint32_t mnc_length = 0;
// Security variables
uint8_t ck[CK_LEN] = {};
uint8_t ik[IK_LEN] = {};
uint8_t ak[AK_LEN] = {};
uint8_t k_asme[KEY_LEN] = {};
uint8_t nh[KEY_LEN] = {};
uint8_t k_enb[KEY_LEN] = {};
uint8_t k_enb_star[KEY_LEN] = {};
uint8_t auts[AKA_AUTS_LEN] = {};
// Helpers to restore security context if HO fails
uint8_t old_k_enb[32] = {};
uint8_t old_ncc = {};
srslte::as_security_config_t old_as_ctx = {};
uint32_t current_ncc = 0;
bool initiated = false;
// Smartcard sub-class which is a port of the PC/SC smartcard implementation
// of WPA Supplicant written by Jouni Malinen <j@w1.fi> and licensed under BSD
// Source: https://w1.fi/cvs.html
class scard
{
public:
scard() : log(NULL){};
~scard(){};
int init(usim_args_t* args, srslte::log* log_);
void deinit();
int select_file(unsigned short file_id, unsigned char* buf, size_t* buf_len);
int _select_file(unsigned short file_id,
unsigned char* buf,
size_t* buf_len,
sim_types_t sim_type,
unsigned char* aid,
size_t aidlen);
long transmit(unsigned char* _send, size_t send_len, unsigned char* _recv, size_t* recv_len);
int get_aid(unsigned char* aid, size_t maxlen);
int get_record_len(unsigned char recnum, unsigned char mode);
int read_record(unsigned char* data, size_t len, unsigned char recnum, unsigned char mode);
int get_imsi(char* imsi, size_t* len);
int parse_fsp_templ(unsigned char* buf, size_t buf_len, int* ps_do, int* file_len);
int read_file(unsigned char* data, size_t len);
int get_mnc_len();
int umts_auth(const unsigned char* _rand,
const unsigned char* autn,
unsigned char* res,
int* res_len,
unsigned char* ik,
unsigned char* ck,
unsigned char* auts);
int pin_needed(unsigned char* hdr, size_t hlen);
int verify_pin(const char* pin);
int get_pin_retry_counter();
private:
/* See ETSI GSM 11.11 and ETSI TS 102 221 for details.
* SIM commands:
* Command APDU: CLA INS P1 P2 P3 Data
* CLA (class of instruction): A0 for GSM, 00 for USIM
* INS (instruction)
* P1 P2 P3 (parameters, P3 = length of Data)
* Response APDU: Data SW1 SW2
* SW1 SW2 (Status words)
* Commands (INS P1 P2 P3):
* SELECT: A4 00 00 02 <file_id, 2 bytes>
* GET RESPONSE: C0 00 00 <len>
* RUN GSM ALG: 88 00 00 00 <RAND len = 10>
* RUN UMTS ALG: 88 00 81 <len=0x22> data: 0x10 | RAND | 0x10 | AUTN
* P1 = ID of alg in card
* P2 = ID of secret key
* READ BINARY: B0 <offset high> <offset low> <len>
* READ RECORD: B2 <record number> <mode> <len>
* P2 (mode) = '02' (next record), '03' (previous record),
* '04' (absolute mode)
* VERIFY CHV: 20 00 <CHV number> 08
* CHANGE CHV: 24 00 <CHV number> 10
* DISABLE CHV: 26 00 01 08
* ENABLE CHV: 28 00 01 08
* UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10
* SLEEP: FA 00 00 00
*/
/* GSM SIM commands */
#define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02
#define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10
#define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00
#define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00
#define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00
#define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08
/* USIM commands */
#define USIM_CLA 0x00
#define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22
#define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00
#define SIM_RECORD_MODE_ABSOLUTE 0x04
#define USIM_FSP_TEMPL_TAG 0x62
#define USIM_TLV_FILE_DESC 0x82
#define USIM_TLV_FILE_ID 0x83
#define USIM_TLV_DF_NAME 0x84
#define USIM_TLV_PROPR_INFO 0xA5
#define USIM_TLV_LIFE_CYCLE_STATUS 0x8A
#define USIM_TLV_FILE_SIZE 0x80
#define USIM_TLV_TOTAL_FILE_SIZE 0x81
#define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6
#define USIM_TLV_SHORT_FILE_ID 0x88
#define USIM_TLV_SECURITY_ATTR_8B 0x8B
#define USIM_TLV_SECURITY_ATTR_8C 0x8C
#define USIM_TLV_SECURITY_ATTR_AB 0xAB
#define USIM_PS_DO_TAG 0x90
/* GSM files
* File type in first octet:
* 3F = Master File
* 7F = Dedicated File
* 2F = Elementary File under the Master File
* 6F = Elementary File under a Dedicated File
*/
#define SCARD_FILE_MF 0x3F00
#define SCARD_FILE_GSM_DF 0x7F20
#define SCARD_FILE_UMTS_DF 0x7F50
#define SCARD_FILE_GSM_EF_IMSI 0x6F07
#define SCARD_FILE_GSM_EF_AD 0x6FAD
#define SCARD_FILE_EF_DIR 0x2F00
#define SCARD_FILE_EF_ICCID 0x2FE2
#define SCARD_FILE_EF_CK 0x6FE1
#define SCARD_FILE_EF_IK 0x6FE2
#define SCARD_CHV1_OFFSET 13
#define SCARD_CHV1_FLAG 0x80
SCARDCONTEXT scard_context;
SCARDHANDLE scard_handle;
long unsigned scard_protocol;
sim_types_t sim_type;
bool pin1_needed;
srslte::log* log;
};
scard sc;
};
} // namespace srsue
#endif // SRSUE_PCSC_USIM_H