static int entersafe_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu,
								   u8 * key, size_t keylen,
								   int cipher,int mac)
{
	 u8 *cipher_data=0,*mac_data=0;
	 size_t cipher_data_size,mac_data_size;
	 int blocks;
	 int r=SC_SUCCESS;

	SC_FUNC_CALLED(card->ctx, 1);

	 assert(card);
	 assert(apdu);

	 if((cipher||mac) && (!key||(keylen!=8 && keylen!=16)))
		  SC_FUNC_RETURN(card->ctx, 3, SC_ERROR_INVALID_ARGUMENTS);

	if (card->ctx->debug >= 6)
	{
		 u8 *sbuf=NULL;
		 size_t ssize=0;
		 r = sc_apdu_get_octets(card->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW);
		 if (r == SC_SUCCESS)
			  sc_apdu_log(card->ctx, sbuf, ssize, 1);
		 free(sbuf);
	}

	 if(cipher)
	 {
		  blocks=(apdu->lc+2)/8+1;
		  cipher_data_size=blocks*8;
		  cipher_data=malloc(cipher_data_size);
		  if(!cipher)
		  {
			   r = SC_ERROR_OUT_OF_MEMORY;
			   goto out;
		  }

		  if((r = entersafe_cipher_apdu(card,apdu,key,keylen,cipher_data,cipher_data_size))<0)
			   goto out;
	 }
	 if(mac)
	 {	 
		  mac_data_size=apdu->lc+4;
		  mac_data=malloc(mac_data_size);
		  r = entersafe_mac_apdu(card,apdu,key,keylen,mac_data,mac_data_size);
		  if(r<0)
			   goto out;
	 }
	 
	 r = sc_transmit_apdu(card,apdu);

out:
	 if(cipher_data)
		  free(cipher_data);
	 if(mac_data)
		  free(mac_data);

	 SC_FUNC_RETURN(card->ctx, 3, r);
}
static int pcsc_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
	sc_apdu_t *apdu)
{
	size_t       ssize, rsize, rbuflen = 0;
	u8           *sbuf = NULL, *rbuf = NULL;
	int          r;

	/* we always use a at least 258 byte size big return buffer
	 * to mimic the behaviour of the old implementation (some readers
	 * seems to require a larger than necessary return buffer).
	 * The buffer for the returned data needs to be at least 2 bytes
	 * larger than the expected data length to store SW1 and SW2. */
	rsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2;
	rbuf     = malloc(rbuflen);
	if (rbuf == NULL) {
		r = SC_ERROR_MEMORY_FAILURE;
		goto out;
	}
	/* encode and log the APDU */
	r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, slot->active_protocol);
	if (r != SC_SUCCESS)
		goto out;
	if (reader->ctx->debug >= 6)
		sc_apdu_log(reader->ctx, sbuf, ssize, 1);

	r = pcsc_internal_transmit(reader, slot, sbuf, ssize,
				rbuf, &rsize, apdu->control);
	if (r < 0) {
		/* unable to transmit ... most likely a reader problem */
		sc_error(reader->ctx, "unable to transmit");
		goto out;
	}
	if (reader->ctx->debug >= 6)
		sc_apdu_log(reader->ctx, rbuf, rsize, 0);
	/* set response */
	r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize);
out:
	if (sbuf != NULL) {
		sc_mem_clear(sbuf, ssize);
		free(sbuf);
	}
	if (rbuf != NULL) {
		sc_mem_clear(rbuf, rbuflen);
		free(rbuf);
	}
	
	return r;
}
static int openct_reader_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
	sc_apdu_t *apdu)
{
	size_t       ssize, rsize, rbuflen = 0;
	u8           *sbuf = NULL, *rbuf = NULL;
	int          r;

	rsize = rbuflen = apdu->resplen + 2;
	rbuf     = malloc(rbuflen);
	if (rbuf == NULL) {
		r = SC_ERROR_MEMORY_FAILURE;
		goto out;
	}
	/* encode and log the APDU */
	r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW);
	if (r != SC_SUCCESS)
		goto out;
	if (reader->ctx->debug >= 6)
		sc_apdu_log(reader->ctx, sbuf, ssize, 1);
	r = openct_reader_internal_transmit(reader, slot, sbuf, ssize,
				rbuf, &rsize, apdu->control);
	if (r < 0) {
		/* unable to transmit ... most likely a reader problem */
		sc_error(reader->ctx, "unable to transmit");
		goto out;
	}
	if (reader->ctx->debug >= 6)
		sc_apdu_log(reader->ctx, rbuf, rsize, 0);
	/* set response */
	r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize);
out:
	if (sbuf != NULL) {
		sc_mem_clear(sbuf, ssize);
		free(sbuf);
	}
	if (rbuf != NULL) {
		sc_mem_clear(rbuf, rbuflen);
		free(rbuf);
	}
	
	return r;
}
예제 #4
0
static int ctapi_transmit(sc_reader_t *reader, sc_apdu_t *apdu)
{
	size_t       ssize, rsize, rbuflen = 0;
	u8           *sbuf = NULL, *rbuf = NULL;
	int          r;

	rsize = rbuflen = apdu->resplen + 2;
	rbuf     = malloc(rbuflen);
	if (rbuf == NULL) {
		r = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}
	/* encode and log the APDU */
	r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW);
	if (r != SC_SUCCESS)
		goto out;
	sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, sbuf, ssize, 1);
	r = ctapi_internal_transmit(reader, sbuf, ssize,
					rbuf, &rsize, apdu->control);
	if (r < 0) {
		/* unable to transmit ... most likely a reader problem */
		sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "unable to transmit");
		goto out;
	}
	sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, rbuf, rsize, 0);
	/* set response */
	r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize);
out:
	if (sbuf != NULL) {
		sc_mem_clear(sbuf, ssize);
		free(sbuf);
	}
	if (rbuf != NULL) {
		sc_mem_clear(rbuf, rbuflen);
		free(rbuf);
	}
	
	return r;
}
예제 #5
0
static int entersafe_mac_apdu(sc_card_t *card, sc_apdu_t *apdu,
							  u8 * key,size_t keylen,
							  u8 * buff,size_t buffsize)
{
	 int r;
	 u8 iv[8];
	 u8 *tmp=0,*tmp_rounded=NULL;
	 size_t tmpsize=0,tmpsize_rounded=0;
	 int outl=0;
	 EVP_CIPHER_CTX ctx;

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);

	 assert(card);
	 assert(apdu);
	 assert(key);
	 assert(buff);

	 if(apdu->cse != SC_APDU_CASE_3_SHORT)
		  return SC_ERROR_INTERNAL;
	 if(keylen!=8 && keylen!=16)
		  return SC_ERROR_INTERNAL;

	 r=entersafe_gen_random(card,iv,sizeof(iv));
	 SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,r,"entersafe gen random failed");

	 /* encode the APDU in the buffer */
	 if ((r=sc_apdu_get_octets(card->ctx, apdu, &tmp, &tmpsize,SC_PROTO_RAW)) != SC_SUCCESS)
		  goto out;

	 /* round to 8 */
	 tmpsize_rounded=(tmpsize/8+1)*8;

	 tmp_rounded = malloc(tmpsize_rounded);
	 if (tmp_rounded == NULL)
	 {
		  r =  SC_ERROR_OUT_OF_MEMORY;
		  goto out;
	 }
	 
	 /*build content and padded buffer by 0x80 0x00 0x00..... */
	 memset(tmp_rounded,0,tmpsize_rounded);
	 memcpy(tmp_rounded,tmp,tmpsize);
	 tmp_rounded[4]+=4;
	 tmp_rounded[tmpsize]=0x80;

	 /* block_size-1 blocks*/
	 EVP_CIPHER_CTX_init(&ctx);
	 EVP_CIPHER_CTX_set_padding(&ctx,0);
	 EVP_EncryptInit_ex(&ctx, EVP_des_cbc(), NULL, key, iv);

	 if(tmpsize_rounded>8){
		  if(!EVP_EncryptUpdate(&ctx,tmp_rounded,&outl,tmp_rounded,tmpsize_rounded-8)){
			   r = SC_ERROR_INTERNAL;
			   goto out;			   
		  }
	 }
	 /* last block */
	 if(keylen==8)
	 {
		  if(!EVP_EncryptUpdate(&ctx,tmp_rounded+outl,&outl,tmp_rounded+outl,8)){
			   r = SC_ERROR_INTERNAL;
			   goto out;			   
		  }
	 }
	 else
	 {
		  EVP_EncryptInit_ex(&ctx, EVP_des_ede_cbc(), NULL, key,tmp_rounded+outl-8);
		  if(!EVP_EncryptUpdate(&ctx,tmp_rounded+outl,&outl,tmp_rounded+outl,8)){
			   r = SC_ERROR_INTERNAL;
			   goto out;			   
		  }
	 }

	 if (!EVP_CIPHER_CTX_cleanup(&ctx)){
		  r = SC_ERROR_INTERNAL;
		  goto out;			   
	 }

	 memcpy(buff,apdu->data,apdu->lc);
	 /* use first 4 bytes of last block as mac value*/
	 memcpy(buff+apdu->lc,tmp_rounded+tmpsize_rounded-8,4);
	 apdu->data=buff;
	 apdu->lc+=4;
	 apdu->datalen=apdu->lc;

out:
	 if(tmp)
		  free(tmp);
	 if(tmp_rounded)
		  free(tmp_rounded);

	 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
}
예제 #6
0
static int boxing_pin_cmd_to_buf(sc_context_t *ctx,
        const struct sc_pin_cmd_data *data,
        unsigned char **pc_to_rdr_secure, size_t *pc_to_rdr_secure_len)
{
    PC_to_RDR_Secure_t *secure;
    abPINDataStucture_Modification_t *modify;
    abPINDataStucture_Verification_t *verify;
    uint16_t wLangId = 0,
             bTeoPrologue2 = 0,
             wPINMaxExtraDigit;
    uint8_t bTimeOut = CCID_PIN_TIMEOUT,
            bNumberMessage = CCID_DISPLAY_DEFAULT,
            bTeoPrologue1 = 0,
            bMsgIndex = 0,
            bMessageType = 0x69,
            bSlot = 0,
            bSeq = 0,
            bBWI = 0xff,
            wLevelParameter = 0,
            bEntryValidationCondition = CCID_ENTRY_VALIDATE,
            bmFormatString, bmPINLengthFormat, bmPINBlockString;
    const struct sc_pin_cmd_pin *pin_ref;
    int r;
    unsigned char *pinapdu = NULL;
    size_t pinapdu_len = 0;

    if (!data || !pc_to_rdr_secure || !pc_to_rdr_secure_len) {
        r = SC_ERROR_INVALID_ARGUMENTS;
        goto err;
    }

    pin_ref = data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ?
        &data->pin2 : &data->pin1;

    wPINMaxExtraDigit = htole16(
            (0xff & pin_ref->min_length) << 8)
            | (pin_ref->max_length & 0xff);

    bmFormatString = CCID_PIN_UNITS_BYTES
        | ((pin_ref->offset & 0xf) << 3);
    switch (pin_ref->encoding) {
        case SC_PIN_ENCODING_ASCII:
            bmFormatString |= CCID_PIN_ENCODING_ASCII;
            break;
        case SC_PIN_ENCODING_BCD:
            bmFormatString |= CCID_PIN_ENCODING_BCD;
            break;
        default:
            r = SC_ERROR_INVALID_ARGUMENTS;
            goto err;
    }

    /* GLP PINs expect the effective PIN length from bit 4 */
	bmPINLengthFormat = pin_ref->encoding == SC_PIN_ENCODING_GLP ?
        0x04 : 0x00;

	if (pin_ref->encoding == SC_PIN_ENCODING_GLP) {
		/* GLP PIN length is encoded in 4 bits and block size is always 8 bytes */
		bmPINBlockString = 0x40 | 0x08;
	} else if (pin_ref->encoding == SC_PIN_ENCODING_ASCII && data->flags & SC_PIN_CMD_NEED_PADDING) {
		bmPINBlockString = pin_ref->pad_length;
	} else {
        bmPINBlockString = 0x00;
    }

    r = sc_apdu_get_octets(ctx, data->apdu, &pinapdu, &pinapdu_len,
            SC_PROTO_T1);
    if (r < 0)
        goto err;

    switch (data->cmd) {
        case SC_PIN_CMD_VERIFY:
            *pc_to_rdr_secure_len = sizeof *secure + 1
                + sizeof *verify + pinapdu_len;
            break;

        case SC_PIN_CMD_CHANGE:
            *pc_to_rdr_secure_len = sizeof *secure + 1
                + sizeof *modify + 3 + pinapdu_len;
            break;

        default:
            r = SC_ERROR_INVALID_ARGUMENTS;
            goto err;
    }

    *pc_to_rdr_secure = malloc(*pc_to_rdr_secure_len);
    if (!*pc_to_rdr_secure) {
        r = SC_ERROR_OUT_OF_MEMORY;
        goto err;
    }
    secure = (PC_to_RDR_Secure_t *) *pc_to_rdr_secure;
    secure->bMessageType = bMessageType;
    secure->dwLength = htole32((*pc_to_rdr_secure_len) - sizeof *secure);
    secure->bSlot = bSlot;
    secure->bSeq = bSeq;
    secure->bBWI = bBWI;
    secure->wLevelParameter = wLevelParameter;

    switch (data->cmd) {
        case SC_PIN_CMD_VERIFY:
            /* bPINOperation */
            *((*pc_to_rdr_secure) + sizeof *secure) = CCID_OPERATION_VERIFY;
            verify = (abPINDataStucture_Verification_t *)
                ((*pc_to_rdr_secure) + sizeof *secure + 1);
            verify->bTimeOut = bTimeOut;
            verify->bmFormatString = bmFormatString;
            verify->bmPINBlockString = bmPINBlockString;
            verify->bmPINLengthFormat = bmPINLengthFormat;
            verify->wPINMaxExtraDigit = wPINMaxExtraDigit;
            verify->bEntryValidationCondition = bEntryValidationCondition;
            verify->bNumberMessage = bNumberMessage;
            verify->wLangId = wLangId;
            verify->bMsgIndex = bMsgIndex;
            verify->bTeoPrologue1 = bTeoPrologue1;
            verify->bTeoPrologue2 = bTeoPrologue2;

            memcpy((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *verify,
                    pinapdu, pinapdu_len);
            break;

        case SC_PIN_CMD_CHANGE:
            /* bPINOperation */
            *((*pc_to_rdr_secure) + sizeof *secure) = CCID_OPERATION_MODIFY;
            modify = (abPINDataStucture_Modification_t *)
                ((*pc_to_rdr_secure) + sizeof *secure + 1);
            modify->bTimeOut = bTimeOut;
            modify->bmFormatString = bmFormatString;
            modify->bmPINBlockString = bmPINBlockString;
            modify->bmPINLengthFormat = bmPINLengthFormat;
            if (!(data->flags & SC_PIN_CMD_IMPLICIT_CHANGE)
                    && data->pin1.offset) {
                modify->bInsertionOffsetOld = data->pin1.offset - 5;
            } else {
                modify->bInsertionOffsetOld = 0;
            }
            modify->bInsertionOffsetNew = data->pin2.offset ? data->pin2.offset - 5 : 0;
            modify->wPINMaxExtraDigit = wPINMaxExtraDigit;
            modify->bConfirmPIN = CCID_PIN_CONFIRM_NEW
                | (data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? 0 : CCID_PIN_INSERT_OLD);
            modify->bEntryValidationCondition = bEntryValidationCondition;
            modify->bNumberMessage = bNumberMessage;
            modify->wLangId = wLangId;
            modify->bMsgIndex1 = bMsgIndex;
            *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 0) =
                bTeoPrologue1;
            *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 1) =
                bTeoPrologue1;
            *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 2) =
                bTeoPrologue1;

            memcpy((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 3,
                    pinapdu, pinapdu_len);
            break;

        default:
            r = SC_ERROR_INVALID_ARGUMENTS;
            goto err;
    }

    r = SC_SUCCESS;

err:
    free(pinapdu);
    if (r < 0 && pc_to_rdr_secure && *pc_to_rdr_secure) {
        free(*pc_to_rdr_secure);
        *pc_to_rdr_secure = NULL;
    }

    return r;
}