📄 card-starcos.c
字号:
sc_starcos_ex_data_t ex_dat; struct sc_cardctl_starcos_key_attr_st *key_attr = NULL; assert(card != NULL && env != NULL); ex_dat.key = SC_STARCOS_PRV_DATA; if (get_ex_data(card, &ex_dat) != SC_SUCCESS) return SC_ERROR_INTERNAL; mse = (starcos_sec_data_t *)ex_dat.data; p = mse->buf; keyID = env->key_ref[0]; algID = env->algorithm_ref & 0xFF; ex_dat.key = SC_STARCOS_EX_KEY(SC_STARCOS_KEY_ATTR, keyID); if (!get_ex_data(card, &ex_dat)) key_attr = (struct sc_cardctl_starcos_key_attr_st *) ex_dat.data; if (env->operation == SC_SEC_OPERATION_SIGN && key_attr && key_attr->flag == SC_SEC_OPERATION_AUTHENTICATE) { /* XXX We want to create a signature with a authentication * key => change operation to SC_SEC_OPERATION_AUTHENTICATE. */ operation = SC_SEC_OPERATION_AUTHENTICATE; algID = 0x01; /* the INTERNAL AUTHENTICATE command does not add * the PKCS#1 digest info structure */ mse->fix_digestInfo = env->algorithm_flags; } else operation = env->operation; switch (operation) { case SC_SEC_OPERATION_DECIPHER: mse->sec_ops = SC_SEC_OPERATION_DECIPHER; mse->p1 = 0x81; mse->p2 = 0xB8; break; case SC_SEC_OPERATION_SIGN: mse->sec_ops = SC_SEC_OPERATION_SIGN; mse->p1 = 0x41; mse->p2 = 0xB6; break; case SC_SEC_OPERATION_AUTHENTICATE: mse->sec_ops = SC_SEC_OPERATION_AUTHENTICATE; mse->p1 = 0x41; mse->p2 = 0xa4; break; default: return SC_ERROR_INVALID_ARGUMENTS; } if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) { *p++ = 0x80; *p++ = 0x01; *p++ = algID; } else if (env->flags & SC_SEC_ENV_ALG_PRESENT && env->algorithm == SC_ALGORITHM_RSA) { /* set the method to use based on the algorithm_flags */ if (operation == SC_SEC_OPERATION_DECIPHER) { if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { *p++ = 0x80; *p++ = 0x01; *p++ = 0x02; } else return SC_ERROR_INVALID_ARGUMENTS; } else if (operation == SC_SEC_OPERATION_SIGN) { *p++ = 0x80; *p++ = 0x01; if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) *p++ = 0x12; else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) *p++ = 0x22; else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5) *p++ = 0x32; else return SC_ERROR_INVALID_ARGUMENTS; } else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796) { if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) *p++ = 0x11; else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) *p++ = 0x21; else return SC_ERROR_INVALID_ARGUMENTS; } else return SC_ERROR_INVALID_ARGUMENTS; } else if (operation == SC_SEC_OPERATION_AUTHENTICATE) { if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { *p++ = 0x80; *p++ = 0x01; *p++ = 0x01; } else return SC_ERROR_INVALID_ARGUMENTS; } else return SC_ERROR_INVALID_ARGUMENTS; } if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) *p++ = 0x83; else *p++ = 0x84; *p++ = env->key_ref_len; memcpy(p, env->key_ref, env->key_ref_len); p += env->key_ref_len; } mse->buf_len = p - mse->buf; return SC_SUCCESS;}static int starcos_compute_signature(struct sc_card *card, const u8 * data, size_t datalen, u8 * out, size_t outlen){ /* NOTE: data should point to a hash value */ int r; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; starcos_sec_data_t *mse; sc_starcos_ex_data_t ex_dat; assert(card != NULL && data != NULL && out != NULL); if (datalen > SC_MAX_APDU_BUFFER_SIZE) SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS); ex_dat.key = SC_STARCOS_PRV_DATA; if (get_ex_data(card, &ex_dat) != SC_SUCCESS) return SC_ERROR_INTERNAL; mse = (starcos_sec_data_t *)ex_dat.data; /* first step: MSE */ if (mse->sec_ops == 0) SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, mse->p1, mse->p2); apdu.data = mse->buf; apdu.datalen = mse->buf_len; apdu.lc = mse->buf_len; apdu.le = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2)); /* the second step depends on the signature method used: * INTERNAL AUTHENTICATE or COMPUTE SIGNATURE */ if (mse->sec_ops == SC_SEC_OPERATION_SIGN) { /* second step: set the hash value */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x90, 0x81); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 0; memcpy(sbuf, data, datalen); apdu.data = sbuf; apdu.lc = datalen; apdu.datalen = datalen; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2)); /* third and final step: calculate the signature */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A, 0x9E, 0x9A); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 256; apdu.lc = 0; apdu.datalen = 0; apdu.sensitive = 1; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { int len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); SC_FUNC_RETURN(card->ctx, 4, len); } } else if (mse->sec_ops == SC_SEC_OPERATION_AUTHENTICATE) { size_t tmp_len; /* second and final step: compute the signature */ sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x10, 0x00); /* create DigestInfo structure ? */ if (mse->fix_digestInfo) { unsigned int flags = mse->fix_digestInfo & SC_ALGORITHM_RSA_HASHES; tmp_len = sizeof(sbuf); r = sc_pkcs1_encode(card->ctx, flags, data, datalen, sbuf, &tmp_len, sizeof(sbuf)); if (r < 0) return r; } else { memcpy(sbuf, data, datalen); tmp_len = datalen; } apdu.lc = tmp_len; apdu.data = sbuf; apdu.datalen = tmp_len; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 256; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); { int len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); SC_FUNC_RETURN(card->ctx, 4, len); } } else SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS); /* clear the old mse state */ memset(mse, 0, sizeof(starcos_sec_data_t)); SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));}static int starcos_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen){ int r; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; starcos_sec_data_t *mse; sc_starcos_ex_data_t ex_dat; assert(card != NULL && crgram != NULL && out != NULL); SC_FUNC_CALLED(card->ctx, 2); if (crgram_len > 255) SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS); /* MSE */ ex_dat.key = SC_STARCOS_PRV_DATA; if (get_ex_data(card, &ex_dat) != SC_SUCCESS) return SC_ERROR_INTERNAL; mse = (starcos_sec_data_t *)ex_dat.data; if (mse->sec_ops == 0) SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, mse->p1, mse->p2); apdu.data = mse->buf; apdu.datalen = mse->buf_len; apdu.lc = mse->buf_len; apdu.le = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2)); /* INS: 0x2A PERFORM SECURITY OPERATION * P1: 0x80 Resp: Plain value * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */ sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x86); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); /* FIXME */ apdu.sensitive = 1; sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */ memcpy(sbuf + 1, crgram, crgram_len); apdu.data = sbuf; apdu.lc = crgram_len + 1; apdu.datalen = crgram_len + 1; apdu.le = 256; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { int len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); SC_FUNC_RETURN(card->ctx, 2, len); } /* clear the old mse state */ memset(mse, 0, sizeof(starcos_sec_data_t)); SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));}static int starcos_check_sw(struct sc_card *card, int sw1, int sw2){ const int err_count = sizeof(starcos_errors)/sizeof(starcos_errors[0]); int i; if (card->ctx->debug >= 3) sc_debug(card->ctx, "sw1 = 0x%02x, sw2 = 0x%02x\n", sw1, sw2); if (sw1 == 0x90) return SC_NO_ERROR; if (sw1 == 0x63 && (sw2 & ~0x0f) == 0xc0 ) { sc_error(card->ctx, "Verification failed (remaining tries: %d)\n", (sw2 & 0x0f)); return SC_ERROR_PIN_CODE_INCORRECT; } /* check starcos error messages */ for (i = 0; i < err_count; i++) if (starcos_errors[i].SWs == ((sw1 << 8) | sw2)) { sc_error(card->ctx, "%s\n", starcos_errors[i].errorstr); return starcos_errors[i].errorno; } /* iso error */ return iso_ops->check_sw(card, sw1, sw2);}static int starcos_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr){ switch (cmd) { case SC_CARDCTL_STARCOS_SET_EX_DATA: return set_ex_data(card, (sc_starcos_ex_data_t *)ptr); case SC_CARDCTL_STARCOS_GET_EX_DATA: return get_ex_data(card, (sc_starcos_ex_data_t *)ptr); case SC_CARDCTL_STARCOS_FREE_EX_DATA: free_ex_data(card, ((sc_starcos_ex_data_t *)ptr)->key); return SC_SUCCESS; case SC_CARDCTL_STARCOS_FREE_ALL_EX_DATA: free_all_ex_data(card); return SC_SUCCESS; default: return SC_ERROR_NOT_SUPPORTED; } return SC_ERROR_NOT_SUPPORTED;}static int starcos_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left){ if (data->cmd == SC_PIN_CMD_VERIFY) { u8 pinId = (u8) data->pin_reference; sc_starcos_ex_data_t ex_dat; ex_dat.key = SC_STARCOS_EX_KEY(SC_STARCOS_PIN_ATTR, pinId); if (get_ex_data(card, &ex_dat) == SC_SUCCESS) { int r; struct sc_cardctl_starcos_pin_attr_st *pin_attr; pin_attr = (struct sc_cardctl_starcos_pin_attr_st *)ex_dat.data; if (!pin_attr->verify_once) return SC_SUCCESS; r = iso_ops->pin_cmd(card, data, tries_left); if (r == SC_SUCCESS) pin_attr->verify_once = 0; return r; } } return iso_ops->pin_cmd(card, data, tries_left);}static struct sc_card_driver * sc_get_driver(void){ struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); if (iso_ops == NULL) iso_ops = iso_drv->ops; starcos_ops = *iso_drv->ops; starcos_ops.match_card = starcos_match_card; starcos_ops.init = starcos_init; starcos_ops.finish = starcos_finish; starcos_ops.select_file = starcos_select_file; starcos_ops.check_sw = starcos_check_sw; starcos_ops.create_file = starcos_create_file; starcos_ops.delete_file = starcos_delete_file; starcos_ops.set_security_env = starcos_set_security_env; starcos_ops.compute_signature = starcos_compute_signature; starcos_ops.decipher = starcos_decipher; starcos_ops.card_ctl = starcos_card_ctl; starcos_ops.pin_cmd = starcos_pin_cmd; return &starcos_drv;}struct sc_card_driver * sc_get_starcos_driver(void){ return sc_get_driver();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -