/* * Create an empty security environment */ static int cardos_create_sec_env(struct sc_profile *profile, sc_card_t *card, unsigned int se_id, unsigned int key_id) { struct sc_cardctl_cardos_obj_info args; struct tlv tlv; unsigned char buffer[64]; int r; tlv_init(&tlv, buffer, sizeof(buffer)); tlv_next(&tlv, 0x83); tlv_add(&tlv, se_id); tlv_next(&tlv, 0x86); tlv_add(&tlv, 0); tlv_add(&tlv, 0); tlv_next(&tlv, 0x8f); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); args.data = buffer; args.len = tlv_len(&tlv); /* ensure we are in the correct lifecycle */ r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN); if (r < 0 && r != SC_ERROR_NOT_SUPPORTED) return r; return sc_card_ctl(card, SC_CARDCTL_CARDOS_PUT_DATA_SECI, &args); }
/* * Create an empty security environment */ static int incrypto34_create_sec_env(struct sc_profile *profile, struct sc_card *card, unsigned int se_id, unsigned int key_id) { struct sc_cardctl_incrypto34_obj_info args; struct tlv tlv; unsigned char buffer[64]; tlv_init(&tlv, buffer, sizeof(buffer)); tlv_next(&tlv, 0x83); tlv_add(&tlv, se_id); tlv_next(&tlv, 0x86); tlv_add(&tlv, 0); tlv_add(&tlv, 0); tlv_next(&tlv, 0x8f); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); tlv_add(&tlv, key_id); args.data = buffer; args.len = tlv_len(&tlv); return sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_PUT_DATA_SECI, &args); }
static int cardos_store_key_component(sc_card_t *card, int algorithm, unsigned int key_id, unsigned int pin_id, unsigned int num, const u8 *data, size_t len, int last, int use_prefix) { struct sc_cardctl_cardos_obj_info args; struct tlv tlv; unsigned char buffer[256]; #ifdef SET_SM_BYTES unsigned int n; #endif int r; /* Initialize the TLV encoder */ tlv_init(&tlv, buffer, sizeof(buffer)); /* Object address */ tlv_next(&tlv, 0x83); tlv_add(&tlv, 0x20|num); /* PSO, n-th component */ tlv_add(&tlv, key_id); /* Object parameters */ tlv_next(&tlv, 0x85); tlv_add(&tlv, CARDOS_KEY_OPTIONS|(last? 0x00 : 0x20)); tlv_add(&tlv, CARDOS_KEY_FLAGS); tlv_add(&tlv, algorithm); tlv_add(&tlv, 0x00); tlv_add(&tlv, 0xFF); /* use count */ tlv_add(&tlv, 0xFF); /* DEK (whatever this is) */ tlv_add(&tlv, 0x00); tlv_add(&tlv, 0x00); /* AC bytes */ tlv_next(&tlv, 0x86); tlv_add(&tlv, pin_id); /* AC USE */ tlv_add(&tlv, pin_id); /* AC CHANGE */ tlv_add(&tlv, pin_id); /* UNKNOWN */ tlv_add(&tlv, 0); /* rfu */ tlv_add(&tlv, 0); /* rfu */ tlv_add(&tlv, 0); /* rfu */ #if 0 tlv_add(&tlv, pin_id); /* AC GENKEY */ #else tlv_add(&tlv, 0); #endif #ifdef SET_SM_BYTES /* it shouldn't be necessary to set the default value */ /* SM bytes */ tlv_next(&tlv, 0x8B); for (n = 0; n < 16; n++) tlv_add(&tlv, 0xFF); #endif /* key component */ tlv_next(&tlv, 0x8f); if (use_prefix != 0) { tlv_add(&tlv, len+1); tlv_add(&tlv, 0); } while (len--) tlv_add(&tlv, *data++); args.data = buffer; args.len = tlv_len(&tlv); /* ensure we are in the correct lifecycle */ r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN); if (r < 0 && r != SC_ERROR_NOT_SUPPORTED) return r; return sc_card_ctl(card, SC_CARDCTL_CARDOS_PUT_DATA_OCI, &args); }
/* * Store a PIN or PUK */ static int cardos_store_pin(sc_profile_t *profile, sc_card_t *card, sc_pkcs15_pin_info_t *pin_info, int puk_id, const u8 *pin, size_t pin_len) { struct sc_cardctl_cardos_obj_info args; unsigned char buffer[256]; unsigned char pinpadded[256]; struct tlv tlv; unsigned int attempts, minlen, maxlen; int r; /* We need to do padding because pkcs15-lib.c does it. * Would be nice to have a flag in the profile that says * "no padding required". */ maxlen = MIN(profile->pin_maxlen, sizeof(pinpadded)); if (pin_len > maxlen) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid pin length: %u (max %u)\n", pin_len, maxlen); return SC_ERROR_INVALID_ARGUMENTS; } memcpy(pinpadded, pin, pin_len); while (pin_len < maxlen) pinpadded[pin_len++] = profile->pin_pad_char; pin = pinpadded; attempts = pin_info->tries_left; minlen = pin_info->min_length; tlv_init(&tlv, buffer, sizeof(buffer)); /* object address: class, id */ tlv_next(&tlv, 0x83); tlv_add(&tlv, 0x00); /* class byte: usage TEST, k=0 */ tlv_add(&tlv, pin_info->reference); /* parameters */ tlv_next(&tlv, 0x85); tlv_add(&tlv, 0x02); /* options byte */ tlv_add(&tlv, attempts & 0xf); /* flags byte */ tlv_add(&tlv, CARDOS_ALGO_PIN); /* algorithm = pin-test */ tlv_add(&tlv, attempts & 0xf); /* errcount = attempts */ /* usecount: not documented, but seems to work like this: * - value of 0xff means pin can be presented any number * of times * - anything less: max # of times before BS object is blocked. */ tlv_add(&tlv, 0xff); /* DEK: not documented, no idea what it means */ tlv_add(&tlv, 0xff); /* ARA counter: number of times the test object can be used before * another verification is required (~ user consent) * (0x00 unlimited usage) */ tlv_add(&tlv, 0x00); tlv_add(&tlv, minlen); /* minlen */ /* AC conditions */ tlv_next(&tlv, 0x86); tlv_add(&tlv, 0x00); /* use: always */ tlv_add(&tlv, pin_info->reference); /* change: PIN */ tlv_add(&tlv, puk_id); /* unblock: PUK */ /* data: PIN */ tlv_next(&tlv, 0x8f); while (pin_len--) tlv_add(&tlv, *pin++); args.data = buffer; args.len = tlv_len(&tlv); /* ensure we are in the correct lifecycle */ r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN); if (r < 0 && r != SC_ERROR_NOT_SUPPORTED) return r; return sc_card_ctl(card, SC_CARDCTL_CARDOS_PUT_DATA_OCI, &args); }
static int incrypto34_store_key_component(struct sc_card *card, int algorithm, unsigned int key_id, unsigned int pin_id, unsigned int num, const u8 *data, size_t len, int last) { int r; struct sc_cardctl_incrypto34_obj_info args; struct tlv tlv; unsigned char buffer[256]; unsigned int n; /* Initialize the TLV encoder */ tlv_init(&tlv, buffer, sizeof(buffer)); /* Object address */ tlv_next(&tlv, 0x83); tlv_add(&tlv, 0x20|num); /* PSO, n-th component */ tlv_add(&tlv, key_id); /* Object parameters */ tlv_next(&tlv, 0x85); tlv_add(&tlv, INCRYPTO34_KEY_OPTIONS|(last? 0x00 : 0x20)); tlv_add(&tlv, INCRYPTO34_KEY_FLAGS); tlv_add(&tlv, algorithm); tlv_add(&tlv, 0x0F); /* Error Counter*/ tlv_add(&tlv, 0xFF); /* use count */ tlv_add(&tlv, 0xFF); /* RFU */ tlv_add(&tlv, 0x00); /* RFU */ tlv_add(&tlv, 0x00); /* RFU */ /* AC bytes */ tlv_next(&tlv, 0x86); tlv_add(&tlv, pin_id); /* AC USE */ tlv_add(&tlv, pin_id); /* AC CHANGE */ tlv_add(&tlv, 0xFF); /* AC_UNBLOCK */ tlv_add(&tlv, 0xFF); /* RFU */ tlv_add(&tlv, 0xFF); /* RFU */ tlv_add(&tlv, 0xFF); /* RFU */ tlv_add(&tlv, 0); /* AC_GENKEY */ tlv_add(&tlv, 0xFF); /* RFU */ tlv_add(&tlv, 0xFF); /* RFU */ tlv_add(&tlv, 0xFF); /* RFU */ /* SM bytes */ tlv_next(&tlv, 0x8B); for (n = 0; n < 16; n++) tlv_add(&tlv, 0xFF); /* key component */ tlv_next(&tlv, 0x8f); tlv_add(&tlv, len+1); tlv_add(&tlv, 0); while (len--) tlv_add(&tlv, *data++); args.data = buffer; args.len = tlv_len(&tlv); r = sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_PUT_DATA_OCI, &args); return r; }
/* * Store a PIN or PUK */ static int incrypto34_store_pin(sc_profile_t *profile, sc_card_t *card, sc_pkcs15_auth_info_t *auth_info, int puk_id, const u8 *pin, size_t pin_len) { struct sc_cardctl_incrypto34_obj_info args; unsigned char buffer[256]; unsigned char pinpadded[16]; struct tlv tlv; unsigned int attempts, minlen, maxlen; if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_OBJECT_NOT_VALID; /* We need to do padding because pkcs15-lib.c does it. * Would be nice to have a flag in the profile that says * "no padding required". */ maxlen = MIN(profile->pin_maxlen, sizeof(pinpadded)); if (pin_len > maxlen) pin_len = maxlen; memcpy(pinpadded, pin, pin_len); while (pin_len < maxlen) pinpadded[pin_len++] = profile->pin_pad_char; pin = pinpadded; attempts = auth_info->tries_left; minlen = auth_info->attrs.pin.min_length; tlv_init(&tlv, buffer, sizeof(buffer)); /* object address: class, id */ tlv_next(&tlv, 0x83); tlv_add(&tlv, 0x00); /* class byte: usage TEST, k=0 */ tlv_add(&tlv, auth_info->attrs.pin.reference); /* parameters */ tlv_next(&tlv, 0x85); tlv_add(&tlv, 0x02); /* options byte */ tlv_add(&tlv, attempts & 0xf); /* flags byte */ tlv_add(&tlv, INCRYPTO34_ALGO_PIN); /* algorithm = pin-test */ tlv_add(&tlv, attempts & 0xf); /* errcount = attempts */ /* usecount: not documented, but seems to work like this: * - value of 0xff means pin can be presented any number * of times * - anything less: max # of times before BS object is blocked. */ tlv_add(&tlv, 0xff); /* DEK: RFU */ tlv_add(&tlv, 0x00); /* ARA counter: the number of times the PIN can be used before the he must be verified again (0 or ff for unlimited usage) */ tlv_add(&tlv, 0x00); tlv_add(&tlv, minlen); /* minlen */ /* AC conditions */ tlv_next(&tlv, 0x86); tlv_add(&tlv, 0x00); /* use: always */ tlv_add(&tlv, auth_info->attrs.pin.reference); /* change: PIN */ tlv_add(&tlv, puk_id); /* unblock: PUK */ tlv_add(&tlv, 0xFF); /*RFU*/ tlv_add(&tlv, 0xFF); /*RFU*/ tlv_add(&tlv, 0xFF); /*RFU*/ tlv_add(&tlv, 0xFF); /*unused on pins*/ tlv_add(&tlv, 0xFF); /*RFU*/ tlv_add(&tlv, 0xFF); /*RFU*/ tlv_add(&tlv, 0xFF); /*RFU*/ /* data: PIN */ tlv_next(&tlv, 0x8f); while (pin_len--) tlv_add(&tlv, *pin++); args.data = buffer; args.len = tlv_len(&tlv); return sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_PUT_DATA_OCI, &args); }