Beispiel #1
0
void print_timestamp_irma(std::string msg, bytestring timestamp)
{
	time_t expires;
									
	if (timestamp[IRMA_VERIFIER_METADATA_OFFSET] != 0x00)
	{
		// Check metadata version number
		if (timestamp[IRMA_VERIFIER_METADATA_OFFSET] != 0x01)
		{
			printf("Invalid metadata attribute found!\n");
		}
		else
		{
			// Reconstruct expiry data from metadata
			expires = 0;
			expires += timestamp[IRMA_VERIFIER_METADATA_OFFSET + 1] << 16;
			expires += timestamp[IRMA_VERIFIER_METADATA_OFFSET + 2] << 8;
			expires += timestamp[IRMA_VERIFIER_METADATA_OFFSET + 3];
			expires *= 86400; // convert days to seconds
		}
	}
	else
	{
		// This is old style
		expires = (timestamp[timestamp.size() - 2] << 8) + (timestamp[timestamp.size() - 1]);
		expires *= 86400; // convert days to seconds
	}

	printf("%s: %s\n", msg.c_str(), ctime(&expires));
}
Beispiel #2
0
bool silvia_pcsc_card::transmit(bytestring APDU, bytestring& data, unsigned short& sw)
{
	if (!transmit(APDU, data))
	{
		return false;
	}
	
	sw = data[data.size() - 2] << 8;
	sw += data[data.size() - 1];
	
	data.resize(data.size() - 2);
	
	return true;
}
void pivacy_cardemu_emulator::process_verify_pin(bytestring& c_apdu, bytestring& r_apdu)
{
	if (c_apdu.size() < 5)
	{
		r_apdu = SW_LENGTH_ERROR;
	}
	else if ((c_apdu[OFS_P1] != 0x00) || ((c_apdu[OFS_P2] != 0x00) && (c_apdu[OFS_P2] != 0x01)))
	{
		ERROR_MSG("Invalid VERIFY PIN request");
		
		r_apdu = SW_DATA_UNKNOWN;
	}
	else
	{
		bytestring supplied_PIN = c_apdu.substr(OFS_CDATA, c_apdu[OFS_LC]);
		
		if (c_apdu[OFS_P2] == 0x00)
		{
			if (supplied_PIN == user_PIN)
			{
				r_apdu = SW_OK;
				
				user_PIN_verified = true;
			}
			else
			{
				r_apdu = SW_PIN_INCORRECT;
				
				user_PIN_verified = false;
			}
		}
		else if (c_apdu[OFS_P2] == 0x01)
		{
			if (supplied_PIN == admin_PIN)
			{
				r_apdu = SW_OK;
				
				admin_PIN_verified = true;
			}
			else
			{
				r_apdu = SW_PIN_INCORRECT;
				
				admin_PIN_verified = false;
			}
		}
	}
}
Beispiel #4
0
std::string hex(const bytestring &input)
{
    std::string output;
    output.reserve(input.size() * 2);
    (void) boost::algorithm::hex(input, std::back_inserter(output));
    return output;
}
Beispiel #5
0
boost::multiprecision::cpp_int le32_to_cpp_int(const bytestring &le32)
{
    boost::multiprecision::cpp_int mpi(0);
    for ( int i = le32.size(); i >= 0; i-- ) {
        mpi = (mpi << 8) + le32[i];
    }
    return mpi;
}
Beispiel #6
0
    /**
     * Add a topic name and request its corresponding topic keys from the security server
     * @param string topic_name
     * @param string port_number port number of the node
     */
    void Client::addTopic(bytestring topic_name, std::string port_number)
    {
        this->topics.push_back(topic_name);
        this->topic_ports[topic_name] = port_number;

        // create topic join request
        Message request(this->id, topic_name, "topic_join");

        // sign with private key
        request.sign(this->key_pair.getPrivate());

        this->log("sent topic join request for " + topic_name.str());

        Message response = send(request, port_number);

        // verify response with security server public key
        if (!response.verify(this->sec_server_key)) {

            this->log("could not verify:", response);

            return;
        }

        // decrypt with private key
        if (!response.decrypt(this->key_pair.getPrivate())) {

            this->log("could not decrypt:", response);

            return;
        }

        if (response.getData().size() == 0) {

            this->log("received an empty topic join response for " + topic_name.str());

            return;
        }

        this->log("received topic keys for " + topic_name.str());

        // store the topic keypair
        TopicKeyPair topic_key_pair(response.getData());
        this->topic_keys[topic_name] = topic_key_pair;
    }
Beispiel #7
0
bool edna_emulator::transceive_control(SCARDHANDLE reader, const bytestring& cmd, bytestring& rdata)
{
	DWORD pcsc_rv;
	DWORD rlen;
	
	rdata.resize(512);
	if ((pcsc_rv = SCardControl(reader, IOCTL_CCID_ESCAPE_DIRECT, cmd.const_byte_str(), cmd.size(), rdata.byte_str(), 512, &rlen)) != SCARD_S_SUCCESS)
	{
		ERROR_MSG("Failed to exchange control command (0x%08X)", pcsc_rv);
		
		SCardDisconnect(reader, SCARD_UNPOWER_CARD);
		SCardReleaseContext(pcsc_context);
		
		return false;
	}
	
	rdata.resize(rlen);
	
	return true;
}
void pivacy_cardemu_emulator::process_select(bytestring& c_apdu, bytestring& r_apdu)
{
	const bytestring IRMA_AID = "F849524D4163617264";
	
	if (c_apdu.size() < 5)
	{
		r_apdu = SW_LENGTH_ERROR;
	}
	else if (c_apdu.substr(OFS_CDATA, c_apdu[OFS_LC]) != IRMA_AID)
	{
		r_apdu = SW_APPLICATION_UNKNOWN;
	}
	else
	{
		// Version 0.8 + emu
		// 
		// Encoded as ISO7816 FCI record
		//
		// 0x6F YZ: FCI template (length: 0xYZ bytes)
		//   0xA5 YZ: Proprietary information encoded in BER-TLV (length: 0xYZ bytes)
		//     0x10 YZ: Sequence, version information (length: 0xYZ bytes)
		//       0x02 01: Integer, major (length: 0x01 byte)
		//       0x02 01: Integer, minor (length: 0x01 byte)
		//       0x02 01: Integer, maintenance (optional, length: 0x01 byte)
		//       0x02 01: Integer, build (optional, length: 0x01 byte)
		//       0x10 YZ: Sequence, extra information (optional, length: 0xYZ bytes)
		//         0x0C YZ: UTF-8 string, identifier (length: 0xYZ bytes)
		//         0x02 01: Integer, counter (optional, length: 0x01 byte)
		//         0x04 YZ: Octet string, data (optional, length: 0xYZ bytes)

		r_apdu = "6F11";
		  r_apdu += "A50F";
		    r_apdu += "100D";
		      r_apdu += "020100";		// major version = 0
		      r_apdu += "020108";		// minor version = 8
		      r_apdu += "1007";
		        r_apdu += "0C03454D55";	// EMU
		r_apdu += "9000";
	}
}
Beispiel #9
0
bool silvia_pcsc_card::transmit(bytestring APDU, bytestring& data_sw)
{
	if (!connected) return false;
	
	data_sw.resize(65536);
	DWORD out_len = 65536;
	SCARD_IO_REQUEST recv_req;
		
	LONG rv = SCardTransmit(
		card_handle, 
		protocol == SCARD_PROTOCOL_T0 ? SCARD_PCI_T0 : SCARD_PCI_T1, 
		APDU.byte_str(), 
		APDU.size(), 
		&recv_req,
		data_sw.byte_str(),
		&out_len);
		
	if (rv != SCARD_S_SUCCESS)
	{
		return false;
	}
	
	data_sw.resize(out_len);
	
	if (data_sw.size() < 2)
	{
		return false;
	}
	
	return true;
}
Beispiel #10
0
    /**
     * Add a topic name and request its corresponding topic keys from the security server
     * @param string topic_name
     * @param string port_number port number of the node
     */
    void CardClient::addTopic(bytestring topic_name, std::string port_number)
    {
        this->topics.push_back(topic_name);
        this->topic_ports[topic_name] = port_number;

        // create topic join request
        Message request(this->id, topic_name, "topic_join");

        request.sign(this->card);

        this->log("sent topic join request for (signed on card) " + topic_name.str());

        Message response = send(request, port_number);

        if (!response.handleTopicKeyResponse(card)) {

            this->log("could not store topic keys for " + topic_name.str());

            return;
        }

        this->log("received topic keys for " + topic_name.str());
    }
Beispiel #11
0
bool silvia_nfc_card::transmit(bytestring APDU, bytestring& data_sw)
{
	if (!connected) return false;
	
	data_sw.resize(65536);
	
	int out_len = nfc_initiator_transceive_bytes(device, APDU.byte_str(), APDU.size(), data_sw.byte_str(), data_sw.size(), 0);

	if (out_len < 2)
	{
		return false;
	}
	
	data_sw.resize(out_len);
	
	if (data_sw.size() < 2)
	{
		return false;
	}
	
	return true;
}
void pivacy_cardemu_emulator::process_prove_commitment(bytestring& c_apdu, bytestring& r_apdu)
{
	if (!proof_started || !proof_have_context_and_D || (selected_credential == NULL))
	{
		r_apdu = SW_WRONG_STATE;
		reset_proof();
	}
	else if ((c_apdu.size() < 5) || (c_apdu[OFS_LC] != (SYSPAR(l_statzk) / 8)))
	{
		r_apdu = SW_LENGTH_ERROR;
		reset_proof();
	}
	else if ((c_apdu[OFS_P1] != 0x00) || (c_apdu[OFS_P2] != 0x00))
	{
		r_apdu = SW_DATA_UNKNOWN;
		reset_proof();
	}
	else
	{
		// Retrieve the nonce
		bytestring nonce = c_apdu.substr(OFS_CDATA, c_apdu[OFS_LC]);
		
		// Generate the proof
		silvia_prover prover(selected_credential->get_issuer_public_key(), selected_credential->get_silvia_credential());
		
		mpz_class c;
		mpz_class A_prime;
		mpz_class e_hat;
		mpz_class v_prime_hat;
		std::vector<mpz_class> a_i_hat;
		std::vector<silvia_attribute*> a_i;
		
		prover.prove(curproof_D, nonce.mpz_val(), curproof_context.mpz_val(), c, A_prime, e_hat, v_prime_hat, a_i_hat, a_i);
		
		// Save proof output
		std::vector<mpz_class>::iterator a_i_hat_it = a_i_hat.begin();
		std::vector<silvia_attribute*>::iterator a_i_it = a_i.begin();
		
		curproof_A_prime = bytestring(A_prime);
		curproof_e_hat = bytestring(e_hat);
		curproof_v_prime_hat = bytestring(v_prime_hat);
		
		/* Add hidden master secret */
		curproof_attributes.push_back(bytestring(*a_i_hat_it));
		a_i_hat_it++;
		
		for (std::vector<bool>::iterator i = curproof_D.begin(); i != curproof_D.end(); i++)
		{
			if ((*i) == true)
			{
				curproof_attributes.push_back(bytestring((*a_i_it)->rep()));
				a_i_it++;
			}
			else
			{
				curproof_attributes.push_back(bytestring(*a_i_hat_it));
				a_i_hat_it++;
			}
		}
		
		// Return c
		r_apdu = bytestring(c);
		r_apdu += SW_OK;
		
		proof_proved = true;
	}
}
void pivacy_cardemu_emulator::process_prove_credential(bytestring& c_apdu, bytestring& r_apdu)
{
	reset_proof();
	
	if ((c_apdu.size() < 5) || (c_apdu[OFS_LC] != 0x28))
	{
		r_apdu = SW_LENGTH_ERROR;
	}
	else if ((c_apdu[OFS_P1] != 0x00) || (c_apdu[OFS_P2] != 0x00))
	{
		r_apdu = SW_WRONG_STATE;
	}
	else
	{
		unsigned short credential_id = (c_apdu[OFS_CDATA] >> 8) + c_apdu[OFS_CDATA + 1];
		
		/* Check if this credential exists */
		selected_credential = NULL;
		
		for (std::vector<pivacy_credential*>::iterator i = credentials.begin(); i != credentials.end(); i++)
		{
			if ((*i)->get_credential_id() == credential_id)
			{
				selected_credential = *i;
			}
		}
		
		if (selected_credential == NULL)
		{
			ERROR_MSG("Attempt to start proof for non-existent credential 0x%04X", credential_id);
			
			r_apdu = SW_CREDENTIAL_UNKNOWN;
		}
		else
		{
			unsigned short D_val = (c_apdu[OFS_CDATA + 2] << 8) + c_apdu[OFS_CDATA + 2 + 1];
			
			curproof_context = c_apdu.substr(OFS_CDATA + 2 + 2, SYSPAR(l_H) / 8);
			
			time_t timestamp = (c_apdu[OFS_CDATA + 2 + (SYSPAR(l_H) / 8) + 2] << 24) +
			                   (c_apdu[OFS_CDATA + 2 + (SYSPAR(l_H) / 8) + 3] << 16) +
			                   (c_apdu[OFS_CDATA + 2 + (SYSPAR(l_H) / 8) + 4] << 8) +
			                   (c_apdu[OFS_CDATA + 2 + (SYSPAR(l_H) / 8) + 5]);
			                   
			INFO_MSG("Started proof with context = %s, D = 0x%04X, timestamp = %d", curproof_context.hex_str().c_str(), D_val, timestamp);
			
			/* Convert D to vector of booleans, start at "expiry" */
			unsigned short D_mask = 0x0002;
			std::vector<const char*> display_attributes;
			
			for (int i = 0; i < selected_credential->get_silvia_credential()->num_attributes(); i++)
			{
				if (FLAG_SET(D_val, D_mask))
				{
					curproof_D.push_back(true);
					
					INFO_MSG("Revealing attribute %s", selected_credential->get_attribute_names()[i].c_str());
					
					display_attributes.push_back(selected_credential->get_attribute_names()[i].c_str());
				}
				else
				{
					curproof_D.push_back(false);
					
					INFO_MSG("Keeping attribute %s hidden", selected_credential->get_attribute_names()[i].c_str());
				}
				
				D_mask <<= 1;
			}
			
			r_apdu = SW_OK;
				
			proof_started = true;
			proof_have_context_and_D = true;
			
			if (ui_connected)
			{
				int consent_result;
				pivacy_rv rv;
				
				if (((rv = pivacy_ui_consent("This terminal", &display_attributes[0], display_attributes.size(), 0, &consent_result) != PRV_OK) ||
				    ((rv = pivacy_ui_show_status(PIVACY_STATE_PRESENT)) != PRV_OK)) && !ui_optional)
				{
					reset_proof();
					
					r_apdu = SW_UNKNOWN_ERROR;
				}
				
				if (rv == PRV_OK)
				{
					if (consent_result == PIVACY_CONSENT_NO)
					{
						reset_proof();
						
						r_apdu = SW_SECURITY_STATUS_NOT_SATISFIED;
					}
				}
			}
		}
	}
}
void pivacy_cardemu_emulator::process_apdu(bytestring& c_apdu, bytestring& r_apdu)
{
	if (!ui_connected)
	{
		if ((pivacy_ui_connect() != PRV_OK) && !ui_optional)
		{
			ERROR_MSG("Not connected to the UI");
			
			r_apdu = SW_UNKNOWN_ERROR;
			
			return;
		}
		
		INFO_MSG("Connected to the Pivacy UI");
		
		ui_connected = true;
	}
	
	if (c_apdu.size() < 4)
	{
		ERROR_MSG("Malformed command APDU of %d bytes", c_apdu.size());
		
		r_apdu = SW_UNKNOWN_ERROR;
		
		return;
	}
	
	switch(c_apdu[OFS_CLA])
	{
	case CLA_ISO:
		switch(c_apdu[OFS_INS])
		{
		case INS_SELECT:
			process_select(c_apdu, r_apdu);
			break;
		case INS_VERIFY_PIN:
			process_verify_pin(c_apdu, r_apdu);
			break;
		default:
			r_apdu = SW_UNKNOWN_INS;
			break;
		}
		break;
	case CLA_PRIVATE:
		switch(c_apdu[OFS_INS])
		{
		case INS_PROVE_CREDENTIAL:
			process_prove_credential(c_apdu, r_apdu);
			break;
		case INS_PROVE_COMMITMENT:
			process_prove_commitment(c_apdu, r_apdu);
			break;
		case INS_PROVE_SIGNATURE:
			process_prove_signature(c_apdu, r_apdu);
			break;
		case INS_GET_RESPONSE:
			process_get_response(c_apdu, r_apdu);
			break;
		default:
			r_apdu = SW_UNKNOWN_INS;
			break;
		}
		break;
	default:
		r_apdu = SW_UNKNOWN_CLA;
	}
}