Ejemplo n.º 1
0
bool EstEidCard::changePin_internal(
	PinType pinType,const PinString &newPin,const PinString &oldPin,bool useUnblockCmd ) {
	mManager.writeLog("[%s:%d]", __FUNCTION__, __LINE__);
	byte cmdChangeCmd[] = {0x00,0x24,0x00};
	bool doSecure = false;

	//mManager.beginTransaction(mConnection);
	if (useUnblockCmd) cmdChangeCmd[1]= 0x2C;
	ByteVec cmd(MAKEVECTOR(cmdChangeCmd));
	cmd.push_back((byte)pinType);

	size_t oldPinLen,newPinLen;
	if (newPin.length() < 4 || oldPin.length() < 4 ) {
		if (!mConnection->isSecure() )
		{
			mManager.endTransaction(mConnection);
			throw std::runtime_error("bad pin length");
		}

		doSecure = true;
	} else {
		oldPinLen = oldPin.length();
		newPinLen = newPin.length();

		ByteVec catPins;
		catPins.resize(oldPinLen + newPinLen);
		copy(oldPin.begin(), oldPin.end(), catPins.begin());
		copy(newPin.begin(), newPin.end(), catPins.begin() + oldPin.length());
		cmd.push_back(LOBYTE(catPins.size()));
		cmd.insert(cmd.end(),catPins.begin(),catPins.end());
	}

	try
	{
		if (doSecure)
			executePinChange(cmd,0,0);
		else
			execute(cmd);
	}
	catch(AuthError &ae)
	{
		mManager.endTransaction(mConnection);
		throw AuthError(ae);
	}
	catch(CardError &e)
	{
		mManager.endTransaction(mConnection);
		if (e.SW1 == 0x63)
			throw AuthError(e);
		else if (useUnblockCmd && e.SW1==0x6a && e.SW2 == 0x80 ) //unblocking, repeating old pin
			throw AuthError(e.SW1,e.SW2,true);
		else
			throw e;
	}
	mManager.endTransaction(mConnection);
	return true;
}
Ejemplo n.º 2
0
bool EstEidCard::changePin_internal(
	PinType pinType,PinString newPin,PinString oldPin,bool useUnblockCmd ) {
	byte cmdChangeCmd[] = {0x00,0x24,0x00};
	bool doSecure = false;

	if (useUnblockCmd) cmdChangeCmd[1]= 0x2C;
	ByteVec cmd(MAKEVECTOR(cmdChangeCmd));
	cmd.push_back((byte)pinType);

	size_t oldPinLen,newPinLen;
	if (newPin.length() < 4 || oldPin.length() < 4 ) {
		if (!mConnection->isSecure() )
			throw std::runtime_error("bad pin length");

		// FIXME: This is probably broken on PC/SC readers and
		//	  it is not known to work on CT-API either
		oldPinLen = (oldPin[0] - '0') * 10 + oldPin[1] - '0';
		newPinLen = (newPin[0] - '0') * 10 + newPin[1]- '0';
		oldPin = PinString(oldPinLen,'0');
		newPin = PinString(newPinLen,'0');
		doSecure = true;
	} else {
		oldPinLen = oldPin.length();
		newPinLen = newPin.length();
	}

	ByteVec catPins;
	catPins.resize(oldPinLen + newPinLen);
	copy(oldPin.begin(), oldPin.end(), catPins.begin());
	copy(newPin.begin(), newPin.end(), catPins.begin() + oldPin.length());
	cmd.push_back(LOBYTE(catPins.size()));
	cmd.insert(cmd.end(),catPins.begin(),catPins.end());

	try {
		if (doSecure)
			executePinChange(cmd,oldPinLen,newPinLen);
		else
			execute(cmd,true);
	} catch(AuthError &ae) {
		throw AuthError(ae);
	} catch(CardError &e) {
		if (e.SW1 == 0x63)
			throw AuthError(e);
		else if (useUnblockCmd && e.SW1==0x6a && e.SW2 == 0x80 ) //unblocking, repeating old pin
			throw AuthError(e.SW1,e.SW2,true);
		else
			throw e;
		}

	return true;
	}
Ejemplo n.º 3
0
void EstEidCardMaintainer::performGenerateNewKeys() {
	card.readCardID();
	card.selectEF(EstEidCard::FILEID_KEYPOINTER);
	ByteVec keyRec = card.readRecord(1);
	if (keyRec.size() != 0x15)
			throw CardDataError("key ptr len is not 0x15");
	ByteVec authPtr(keyRec.begin() + 0x09, keyRec.begin() + 0x0A);
	ByteVec signPtr(keyRec.begin() + 0x13, keyRec.begin() + 0x14);

	card.selectMF();
	card.setSecEnv(3);
	card.selectDF(EstEidCard::FILEID_APP);
	card.setSecEnv(3);
	/*CardBase::FCI fileInfo = */card.selectEF(0x0013);
	card.readEF(1);
}
Ejemplo n.º 4
0
/* Old Mozilla plugin */
std::string EsteidAPI::getCertificatesMoz()
{
    whitelistRequired();

    try { RTERROR_TO_SCRIPT(
        ByteVec bv = m_service->getSignCert();
        X509Certificate cert(bv);
        std::ostringstream buf;

        /* Return "compatible" JSON */
        buf << "({certificates:[{";
        buf << "id:'" << MAGIC_ID << "',";
        buf << "cert:'";
        for(ByteVec::const_iterator it = bv.begin(); it!=bv.end();it++)
            buf << std::setfill('0') << std::setw(2) << std::hex << (short)*it;
        buf << "',";
        buf << "CN:'" << cert.getSubjectCN() << "',";
        buf << "issuerCN:'" << cert.getIssuerCN() << "',";
        // JS using this old API expects the exact string "Non-Repudiation"
        buf << "keyUsage:'Non-Repudiation',";
        buf << "validFrom: new Date(),"; // TODO: Date(YYYY,MM,DD,HH,mm,SS)
        buf << "validTo: new Date()}],"; // TODO: Date(YYYY,MM,DD,HH,mm,SS)
        buf << "returnCode:0})";

        return buf.str();

    // TODO: Return proper error code from plugin (when it's implemented)
    )} catch(...) { return "({returnCode: 12})"; }
}
Ejemplo n.º 5
0
void EstEidCard::readPersonalData_internal(vector<string>& data,int recStart,int recEnd)
{
	mManager.writeLog("[%s:%d]", __FUNCTION__, __LINE__);
	selectMF(true);
	selectDF(FILEID_APP,true);
	FCI fileInfo = selectEF(0x5044);

	if (fileInfo.recCount != 0x10 && fileInfo.recCount != 0x0A && fileInfo.recCount != 0x14)
	{
		throw CardDataError("personal data file does not contain 16 or 10 records");
	}

	data.resize(min(recEnd,0x10) + 1 );
	for (int i=recStart; i <= recEnd; i++)
	{
		ByteVec record;
		try
		{
			record = readRecord(i);
		}
		catch(...)
		{
			throw;
		}
		string& ret = data[i];
		for (ByteVec::iterator c = record.begin();c!=record.end();c++)
			ret+= *c ;
		/* EstEID 3.0 has fixed length, space padded data file records. Trim from the end */
		if (getCardVersion() == VER_3_0)
			ret.erase(std::find_if(ret.rbegin(), ret.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), ret.end());
	}
}
Ejemplo n.º 6
0
void dump(std::ostream *sout,string prefix,ByteVec &cmd) {
	if (!sout) return;
	*sout << prefix;
	for(ByteVec::iterator it=cmd.begin();it < cmd.end(); it++ ) 
		*sout << std::hex << std::setfill('0') << std::setw(2) <<  (int) *it << " ";
	*sout << std::endl << std::endl;
	}
Ejemplo n.º 7
0
string CTAPIManager::getReaderState(uint index)
{
	string retval;
	ensureReaders(index);
	cPort *dri = mPorts[index];
//	byte cmd[] = {0x20,INS_GETSTATUS,0x00,0x80,0x00}; //GET STATUS, CT, all ICC status
//	byte cmd[] = {0x20,INS_GETSTATUS,0x00,0x81,0x00}; //GET STATUS, CT, functional spec
	byte cmd[] = {0x20,INS_GETSTATUS,0x01,0x80,0x00}; //GET STATUS, ICC0, ICC0 status

	initclose _i(dri);

	ByteVec resp;
	dri->performCmd(CTDAD_CT,MAKEVECTOR(cmd),resp,mLogger);
	if(resp.size() != 3) {
		if (resp.size() == 2) //workaround for openct
			resp.insert(resp.begin(),0x80);
		else
			throw CTAPIError("getReaderState0",0,resp.size(),0,0);
		}
	if (resp[0] != 0x80)
		throw CTAPIError("getReaderState1",0,resp.size(),resp[0],0);
	byte statusICC0 = resp[2];
	if (statusICC0 & 0x01)
		retval+= "PRESENT|";
	else
		retval+= "EMPTY|";
	if ((statusICC0 & 0x6) == 0x2)
		retval+= "UNPOWERED|";
	if ((statusICC0 & 0x6) == 0x4)
		retval+= "INUSE|";
	if (retval.length() > 0 )
		retval = retval.substr(0,retval.length()-1);
	return retval;
}
Ejemplo n.º 8
0
CardBase::FCI EstEidCard::parseFCI(ByteVec fci)
{
	ByteVec tag;

	FCI tmp;
	tmp.fileID = 0;
	if (fci.size() < 0x0B ||
		(fci[0] != tagFCP && fci[0] != tagFCI)	||
		fci.size()-2 != fci[1] )
		throw CardDataError("invalid fci record");

	if (getCardVersion() == VER_3_0)
		fci = ByteVec(fci.begin()+ 4, fci.end());
	else
		fci = ByteVec(fci.begin()+ 2, fci.end());

	tag = getTag(0x83, 2, fci);
	if (tag.size() != 2)
		throw CardDataError("file name record invalid length, not two bytes");

	tmp.fileID = MAKEWORD(tag[1],tag[0]);

	tag = getTag(0x82, 0, fci);
	switch (tag[0] & 0x3F) {
		case 0x38: //DF
		case 0x01: //binary
			if (tag.size() != 1)
				throw CardDataError("linear variable file descriptor not 1 bytes long");
			tag = getTag(0x85,2,fci);
			tmp.fileLength = MAKEWORD(tag[1],tag[0]);
			break;
		case 0x02:
		//linear variable
		case 0x04:
			if (tag.size() != 5)
				throw CardDataError("linear variable file descriptor not 5 bytes long");
			tmp.recMaxLen	= MAKEWORD( tag[0x03], tag[0x02] );
			tmp.recCount	= tag[0x04];
			tmp.fileLength	= 0;
			break;

		default:
			throw CardDataError("invalid filelen record, unrecognized tag");
		}
	return tmp;
}
Ejemplo n.º 9
0
string CTAPIManager::getReaderName(uint index)
{
	string retval;
	ensureReaders(index);
	cPort *dri = mPorts[index];
	byte cmd[] = {0x20,INS_GETSTATUS,0x00,0x46,0x00};
	initclose _i(dri);

	ByteVec resp;
	dri->performCmd(CTDAD_CT,MAKEVECTOR(cmd),resp,mLogger);
	if (resp[0] != 0x46) {
		if (resp.size() != 2) { //openCT
			throw CTAPIError("getReaderName",0,resp.size(),resp[0],resp[1]);
			}
		return "opensc?";
		}
	resp.erase(resp.begin(),resp.begin()+2);
	retval.resize(resp.size());
	copy(resp.begin(),resp.end(),retval.begin());
	return retval;
}
Ejemplo n.º 10
0
ByteVec AUTH_SESSION::ParmEncrypt(ByteVec& parm, bool directionCommand)
{
    ByteVec nonceNewer, nonceOlder;

    if (directionCommand) {
        nonceNewer = NonceCaller;
        nonceOlder = NonceTpm;
    } else {
        nonceNewer = NonceTpm;
        nonceOlder = NonceCaller;
    }

    if (Symmetric.algorithm != TPM_ALG_ID::AES) {
        throw domain_error("Only AES parm encryption is implemtented");
    }

    if (Symmetric.keyBits != 128) {
        throw domain_error("Only AES-128 parm encryption is implemtented");
    }

    if (Symmetric.mode != TPM_ALG_ID::CFB) {
        throw domain_error("Only AES-128-CFB parm encryption is implemtented");
    }

    int numKdfBits = 256;
    int numBits = 128;

    ByteVec encKey = SessionKey;
    ByteVec keyInfo = KDF::KDFa(HashAlg, encKey, "CFB", nonceNewer, nonceOlder, numKdfBits);

    size_t keySize = numBits / 8;

    ByteVec key(keyInfo.begin(), keyInfo.begin() + keySize);
    ByteVec iv(keyInfo.begin() + keySize, keyInfo.end());

    ByteVec xcrypted = CryptoServices::CFBXncrypt(directionCommand, TPM_ALG_ID::AES, key, iv, parm);

    return xcrypted;
}
Ejemplo n.º 11
0
ByteVec EstEidCard::calcSign_internal(AlgType type,KeyType keyId,ByteVec hash,bool withOID)
{
	byte signCmdSig[] = {0x00,0x2A,0x9E,0x9A};
	byte signCmdAut[] = {0x00,0x88,0x00,0x00};
	byte hashHdMD5[] = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
	byte hashHdSHA1[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};

	ByteVec cmd,header;
	if (keyId == 0 )
		cmd = MAKEVECTOR(signCmdAut);
	else
		cmd = MAKEVECTOR(signCmdSig);

	if (withOID) {
		switch(type) {
			case MD5:
				header = MAKEVECTOR(hashHdMD5);
				break;
			case SHA1:
				header = MAKEVECTOR(hashHdSHA1);
				break;
			default:
				throw std::runtime_error("cannot calculate SSL signature with OID");
			}
		cmd.push_back((byte) (header.size() + hash.size()));
		cmd.insert(cmd.end(), header.begin(), header.end());
	}
	else
		cmd.push_back((byte)hash.size());

	setSecEnv(1);

	cmd.insert(cmd.end(), hash.begin(), hash.end());
	ByteVec result;
	try {
		result = execute(cmd);
	} catch(CardError e) {
		if (e.SW1 == 0x69 && (e.SW2 == 0x82 || e.SW2 == 0x00 || e.SW2 == 0x85 ))
			throw AuthError(e);
		throw e;
		}
	return result;
}
Ejemplo n.º 12
0
MojErr MojDbLevelQuery::seekImpl(const ByteVec& key, bool desc, bool& foundOut)
{
	if (key.empty()) {
		// if key is empty, seek to beginning (or end if desc)
		MojErr err = getKey(foundOut, SeekEmptyFlags[desc]);
		MojErrCheck(err);
	} else {
		// otherwise seek to the key
		MojErr err = m_key.fromBytes(key.begin(), key.size());
		MojErrCheck(err);
		err = getKey(foundOut, SeekFlags);
		MojErrCheck(err);
		// if descending, skip the first result (which is outside the range)
		if (desc) {
			err = next(foundOut);
			MojErrCheck(err);
		}
	}
	return MojErrNone;
}
Ejemplo n.º 13
0
ByteVec EstEidCard::RSADecrypt_internal(ByteVec cipher)
{
	byte modEnv1[] = {0x00,0x22,0x41,0xA4,0x02,0x83,0x00};
	byte modEnv2[] = {0x00,0x22,0x41,0xB6,0x02,0x83,0x00};
	byte modEnv0[] = {0x00,0x22,0x41,0xB8,0x05,0x83,0x03,0x80};

	selectMF(true);
	selectDF(FILEID_APP,true);
	selectEF(FILEID_KEYPOINTER,true);
	ByteVec keyRec = readRecord(1);
	if (keyRec.size() != 0x15)
		throw CardDataError("key ptr len is not 0x15");
	ByteVec cmd(MAKEVECTOR(modEnv0));
	cmd.insert(cmd.end(),&keyRec[0x9],&keyRec[0xB]);

	setSecEnv(6);
	execute(MAKEVECTOR(modEnv1),true);
	execute(MAKEVECTOR(modEnv2),true);
	execute(cmd,true);

	byte decrpt[] = {0x00,0x2A,0x80,0x86,0x81,0x00};
	ByteVec decCmd(MAKEVECTOR(decrpt));
	decCmd.insert(decCmd.end(),cipher.begin(),cipher.end());

	ByteVec result;
	try {
		result = execute(decCmd,false);
	} catch(CardError e) {
/*		if (e.SW1 == 0x69 && e.SW2 == 0x88 ) {
			reverse(decCmd.begin() + 6, decCmd.end());
			result = execute(decCmd,false);
			return result;
			}*/
		if (e.SW1 == 0x69 && (e.SW2 == 0x82 || e.SW2 == 0x00 || e.SW2 == 0x88  || e.SW2 == 0x85
			/*|| e.SW1 == 0x64 */|| e.SW1 == 0x6B ))
			throw AuthError(e);
		throw e;
		}
	return result;
}
Ejemplo n.º 14
0
int MojDbIsamQuery::compareKey(const ByteVec& key)
{
	return MojLexicalCompare(m_keyData, m_keySize, key.begin(), key.size());
}
Ejemplo n.º 15
0
// Called within a transaction
ByteVec EstEidCard::RSADecrypt_internal(const ByteVec &cryptogram)
{
	mManager.writeLog("[%s:%d]", __FUNCTION__, __LINE__);
	if (_card_version == VER_3_0 && cryptogram.size() != 256)
		throw std::runtime_error("2048 bit keys but cryptogram is not 256 bytes!");
	if (_card_version != VER_3_0 && cryptogram.size() != 128)
		throw std::runtime_error("cryptogram is not 128 bytes!");

	byte modEnv1[] = {0x00,0x22,0x41,0xA4,0x02,0x83,0x00};
	byte modEnv2[] = {0x00,0x22,0x41,0xB6,0x02,0x83,0x00};
	byte modEnv0[] = {0x00,0x22,0x41,0xB8,0x05,0x83,0x03,0x80};

	//mManager.beginTransaction(mConnection);
	selectMF(true);
	selectDF(FILEID_APP,true);
	selectEF(FILEID_KEYPOINTER,true);
	ByteVec keyRec = readRecord(1);
	if (keyRec.size() != 0x15)
	{
		mManager.endTransaction(mConnection);
		throw CardDataError("key ptr len is not 0x15");
	}
	ByteVec cmd(MAKEVECTOR(modEnv0));
	cmd.insert(cmd.end(),&keyRec[0x9],&keyRec[0xB]);

	setSecEnv(6);
	execute(MAKEVECTOR(modEnv1));
	execute(MAKEVECTOR(modEnv2));
	execute(cmd);

	ByteVec result;

	try
	{
		if (_card_version == VER_3_0) {
			// Use chaining for decryption
			byte decrypt_chain1[] = {0x10, 0x2A, 0x80, 0x86, 0xFF, 0x00};
			byte decrypt_chain2[] = {0x00, 0x2A, 0x80, 0x86, 0x02};
			ByteVec first_command(MAKEVECTOR(decrypt_chain1));
			ByteVec second_command(MAKEVECTOR(decrypt_chain2));
			first_command.insert(first_command.end(), cryptogram.begin(), cryptogram.end()-2);
			second_command.insert(second_command.end(), cryptogram.end()-2, cryptogram.end());
			execute(first_command, 2);
			result = execute(second_command, 4);
		} else {
			byte decrypt[] = {0x00, 0x2A, 0x80, 0x86, 0x81, 0x00};
			ByteVec decrypt_command(MAKEVECTOR(decrypt));
			decrypt_command.insert(decrypt_command.end(), cryptogram.begin(), cryptogram.end());
			result = execute(decrypt_command, 4);
		}
	}
	catch(CardError e)
	{
		mManager.endTransaction(mConnection);
		if (e.SW1 == 0x69 && (e.SW2 == 0x82 || e.SW2 == 0x00 || e.SW2 == 0x88  || e.SW2 == 0x85
			/*|| e.SW1 == 0x64 */|| e.SW1 == 0x6B ))
			throw AuthError(e);
		throw e;
	}
	mManager.endTransaction(mConnection);
	return result;
}
Ejemplo n.º 16
0
ByteVec EstEidCard::calcSign_internal(AlgType type,KeyType keyId,const ByteVec &hash,bool withOID)
{
	mManager.writeLog("[%s:%d]", __FUNCTION__, __LINE__);
	byte signCmdSig[] = {0x00,0x2A,0x9E,0x9A};
	byte signCmdAut[] = {0x00,0x88,0x00,0x00};
	byte hashHdMD5[] = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
	byte hashHdSHA1[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
	byte hashHdSHA224[] = {0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c};
	byte hashHdSHA256[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
	byte hashHdSHA384[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
	byte hashHdSHA512[] = {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};

	ByteVec cmd,header;
	if (keyId == 0 )
	{
		cmd = MAKEVECTOR(signCmdAut);
	}
	else
	{
		cmd = MAKEVECTOR(signCmdSig);
	}

	if (withOID)
	{
		switch(type)
		{
			case MD5:
				header = MAKEVECTOR(hashHdMD5);
				break;
			case SHA1:
				header = MAKEVECTOR(hashHdSHA1);
				break;
			case SHA224:
				header = MAKEVECTOR(hashHdSHA224);
				break;
			case SHA256:
				header = MAKEVECTOR(hashHdSHA256);
				break;
			case SHA384:
				header = MAKEVECTOR(hashHdSHA384);
				break;
			case SHA512:
				header = MAKEVECTOR(hashHdSHA512);
				break;
			default:
				throw std::runtime_error("cannot calculate SSL signature with OID");
		}
		cmd.push_back((byte) (header.size() + hash.size()));
		cmd.insert(cmd.end(), header.begin(), header.end());
	}
	else
		cmd.push_back((byte)hash.size());

	setSecEnv(1);

	cmd.insert(cmd.end(), hash.begin(), hash.end());
	ByteVec result;
	try
	{
//#ifdef _WIN32
		//setVersion();//SIGSEGs Under Linux. Needed only for Windows MiniDriver
//#endif
		if(_card_version != VER_3_0)
		{
			mManager.writeLog("[%s:%d] Sending APDU case 4 (Card version %i)", __FUNCTION__, __LINE__, getCardVersion());
			result = execute(cmd, 4);
		}
		else
		{
			mManager.writeLog("[%s:%d] Sending default APDU case (Card version %i)", __FUNCTION__, __LINE__, getCardVersion());
			result = execute(cmd);
		}
	}
	catch(CardError e)
	{
		if (e.SW1 == 0x69 && (e.SW2 == 0x82 || e.SW2 == 0x00 || e.SW2 == 0x85 ))
			throw AuthError(e);
		throw e;
	}
	return result;
}