Ejemplo n.º 1
0
/*
 * 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);
}
Ejemplo n.º 2
0
/*
 * 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);
}
Ejemplo n.º 3
0
int cli_extract_all(dz_t *dz, int name_mod) {

        int status = -1;
        tlv_t tlv;
        off_t off;

        if (tlv_init(&tlv) == -1) {
                LOGERROR("tlv_init");
                return -1;
        }

        while ((off = dz_next_tlv(dz, &tlv)) != EOD) {
                const char *type_str;
                int type, len;

                if (off == -1) {
                        goto DESTROY;
                }

                type = tlv_get_type(&tlv);

                if (type == TLV_PAD1 || type == TLV_PADN) {
                        continue;
                }

                if (type == TLV_LONGH) {
                        if (cli_extract_ltlv(dz, &tlv, off, name_mod) != 0) {
                                LOGERROR("cli_extract_ltlv failed");
                                goto DESTROY;
                        }
                        dz_set_offset(dz, off + ltlv_get_total_length(&tlv));
                } else if (cli_extract_tlv(dz, off, name_mod) != 0) {
                        LOGERROR("cli_extract_tlv failed");
                        goto DESTROY;
                }
        }

        /* No error occurred */
        status = 0;

DESTROY:
        if (tlv_destroy(&tlv) != 0) {
                LOGERROR("tlv_destroy failed");
                status = -1;
        }

        return status;
}
Ejemplo n.º 4
0
Archivo: tlv.c Proyecto: dtaht/hnetd
static struct tlv_attr *
tlv_add(struct tlv_buf *buf, struct tlv_attr *pos, int id, int payload)
{
	int offset = attr_to_offset(buf, pos);
	int required = (offset - TLV_COOKIE + sizeof(struct tlv_attr) + payload) - buf->buflen;
	struct tlv_attr *attr;

	if (required > 0) {
		tlv_buf_grow(buf, required);
		attr = offset_to_attr(buf, offset);
	} else {
		attr = pos;
	}

	tlv_init(attr, id, payload + sizeof(struct tlv_attr));
	tlv_fill_pad(attr);
	return attr;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
/*
 * 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);
}
Ejemplo n.º 7
0
static void hncp_ok(void)
{
  hncp o = create_hncp();
  int t = 123000;
  int i;

  /* Pushing in a new subscriber should result in us being called. */
  smock_is_empty();
  smock_push_bool("node_callback", true);
  hncp_subscribe(o, &dummy_subscriber_1);
  hncp_subscribe(o, &dummy_subscriber_2);
  hncp_subscribe(o, &dummy_subscriber_3);
  hncp_subscribe(o, &dummy_subscriber_4);

  smock_is_empty();
  one_join(true);
  smock_push_int("schedule", 0);
  hncp_if_set_enabled(o, dummy_ifname, true);
  smock_is_empty();

  /* Ok. We're cooking with gas. */
  smock_push_int("time", t);
  smock_push_int("random", 0);
  smock_push_int("schedule", HNCP_TRICKLE_IMIN / 2);
  hncp_run(o);
  smock_is_empty();

  t += HNCP_TRICKLE_IMIN / 2 - 1;
  smock_push_int("time", t);
  smock_push_int("schedule", 1);
  hncp_run(o);
  smock_is_empty();

  t += 1;
  /* Ok. we get timestamp -> woah, need to do something. */
  smock_push_int("time", t);

  /* Should send stuff on an interface. */
  smock_push("sendto_ifname", dummy_ifname);
  smock_push("sendto_dst", &o->multicast_address);
  smock_push_int("sendto_return", 1);

  /* And schedule next one (=end of interval). */
  smock_push_int("schedule", HNCP_TRICKLE_IMIN / 2);
  hncp_run(o);
  smock_is_empty();

  /* overshoot what we were asked for.. shouldn't be a problem. */
  t += HNCP_TRICKLE_IMIN;
  smock_push_int("time", t);
  /* should be queueing next send, and now we go for 'max' value. */
  smock_push_int("random", 999);
  smock_push_int("schedule", 2 * HNCP_TRICKLE_IMIN * (1000 + 999) / 2000);
  hncp_run(o);
  smock_is_empty();

  /* run the clock until we hit HNCP_TRICKLE_IMAX/2 delay; or we run
   * out of iterations. */
  check_timing = false;
  check_send = false;
  check_random = false;
  want_send = 0;
  for (i = 0 ; i < 100 ; i++)
    {
      current_hnetd_time = t;
      want_schedule = 0;
      hncp_run(o);
      if (want_schedule >= (HNCP_TRICKLE_IMAX / 2))
        {
          sput_fail_unless(want_schedule <= HNCP_TRICKLE_IMAX, "reasonable timeout");
          break;
        }
      t += want_schedule;
      current_hnetd_time += want_schedule;
    }
  sput_fail_unless(want_send <= i / 2, "few sends");
  sput_fail_unless(i < 100, "did not encounter big enough delta");
  /* then, run for few more iterations, making sure we don't hit too long ones. */
  want_send = 0;
  for (i = 0 ; i < 10 ; i++)
    {
      current_hnetd_time = t;
      want_schedule = 0;
      hncp_run(o);
      sput_fail_unless(want_schedule <= HNCP_TRICKLE_IMAX, "reasonable timeout");
      t += want_schedule;
      current_hnetd_time += want_schedule;
    }
  sput_fail_unless(want_send > 0 && want_send <= i / 2, "few sends");
  check_timing = true;
  check_send = true;
  check_random = true;

  /* Ok, Trickle was in a stable state 'long' time. Make sure the
   * state resets once we push something new in. */
  struct tlv_attr ta;
  L_NOTICE("add tlv a");
#define TLV_ID_A 123
#define TLV_ID_B 125
#define TLV_ID_C 127
#define TLV_ID_D 124
  tlv_init(&ta, TLV_ID_A, 4);
  smock_push_int("schedule", 0);
  smock_push_int("local_tlv_callback", TLV_ID_A);
  hncp_add_tlv(o, &ta);
  smock_is_empty();

  L_NOTICE("add tlv b");
  tlv_init(&ta, TLV_ID_B, 4);
  /* should NOT cause extra schedule! */
  smock_push_int("local_tlv_callback", TLV_ID_B);
  hncp_add_tlv(o, &ta);
  smock_is_empty();

  L_NOTICE("running.");
  printf("last run starting\n");
  smock_push_int("time", t);
  smock_push_int("random", 0);
  smock_push_int("schedule", 0);

  /* Should get notification about two added TLVs. */
  smock_push_int("tlv_callback", TLV_ID_A);
  smock_push_int("tlv_callback", TLV_ID_B);
  smock_push_bool("republish_callback", true);
  hncp_run(o);
  smock_is_empty();

  /* Adding / removing last entry have special handling. So let's
   * test both by adding and removing tlv c (which > a, b). */

  /* Our interest in timing has waned by now though, so we disable
   * those checks. */
  check_timing = false;
  check_random = false;

  /* So, let's add one more TLV. Make sure we get notification about it. */
  L_NOTICE("add tlv c");
  tlv_init(&ta, TLV_ID_C, 4);
  smock_push_int("local_tlv_callback", TLV_ID_C);
  hncp_add_tlv(o, &ta);
  smock_is_empty();
  smock_push_int("tlv_callback", TLV_ID_C);
  smock_push_bool("republish_callback", true);
  hncp_run(o);
  smock_is_empty();

  /* Remove it. */
  L_NOTICE("remove tlv c");
  smock_push_int("local_tlv_callback", -TLV_ID_C);
  hncp_remove_tlv(o, &ta);
  smock_is_empty();
  smock_push_int("tlv_callback", -TLV_ID_C);
  smock_push_bool("republish_callback", true);
  hncp_run(o);
  smock_is_empty();

  /* Add TLV D in the middle. */
  L_NOTICE("add tlv d");
  tlv_init(&ta, TLV_ID_D, 4);
  smock_push_int("local_tlv_callback", TLV_ID_D);
  hncp_add_tlv(o, &ta);
  smock_is_empty();
  smock_push_int("tlv_callback", TLV_ID_D);
  smock_push_bool("republish_callback", true);
  hncp_run(o);
  smock_is_empty();

  /* Unsubscribing should result in callbacks too. */
  L_NOTICE("unsubscribe");
  smock_push_int("local_tlv_callback", -TLV_ID_A);
  smock_push_int("local_tlv_callback", -TLV_ID_D);
  smock_push_int("local_tlv_callback", -TLV_ID_B);
  smock_push_int("tlv_callback", -TLV_ID_A);
  smock_push_int("tlv_callback", -TLV_ID_D);
  smock_push_int("tlv_callback", -TLV_ID_B);
  smock_push_bool("node_callback", false);
  hncp_unsubscribe(o, &dummy_subscriber_1);
  hncp_unsubscribe(o, &dummy_subscriber_2);
  hncp_unsubscribe(o, &dummy_subscriber_3);
  hncp_unsubscribe(o, &dummy_subscriber_4);
  smock_is_empty();

  /* Re-enable checks */
  check_timing = true;
  check_random = true;

  /* no unregisters at end, as we first kill io, and then flush
   * structures (socket kill should take care of it in any case). */
  destroy_hncp(o);
}
Ejemplo n.º 8
0
int cmd_extract(int argc , char **argv, char *dz_path) {
        dz_t dz;
        tlv_t tlv;
        long off;
        int fd;
        size_t real_size;
        char *data;
        char *path;

        if (argc != 2) {
                fprintf(stderr, "cmd extract : <offset> <path> <dazibao>\n");
                return DZ_ARGS_ERROR;
        }

        /* If the offset doesn't start with a character between '0' and '9', it
         * must be wrong.
         */
        if (argv[0][0] < 48 || argv[0][0] > 57) {
                fprintf(stderr,
                        "Usage:\n       extract <offset> <file> <dazibao>\n");
                return DZ_ARGS_ERROR;
        }

        off = str2dec_positive(argv[0]);

        if (off < DAZIBAO_HEADER_SIZE) {
                fprintf(stderr, "wrong offset\n");
                return DZ_OFFSET_ERROR;
        }

        if (dz_open(&dz, dz_path, O_RDWR) < 0) {
                fprintf(stderr, "Error while opening the dazibao\n");
                return -1;
        }

        if (dz_check_tlv_at(&dz, off, -1,NULL) <= 0) {
                fprintf(stderr, "no such TLV\n");
                dz_close(&dz);
                return DZ_OFFSET_ERROR;
        }

        if (tlv_init(&tlv) < 0) {
                printf("error to init tlv\n");
                dz_close(&dz);
                return -1;
        }

        if (choose_tlv_extract(&dz,&tlv,off) < 0) {
                printf("error to init tlv\n");
                tlv_destroy(&tlv);
                dz_close(&dz);
                return -1;
        }

        if (dz_close(&dz) < 0) {
                fprintf(stderr, "Error while closing the dazibao\n");
                tlv_destroy(&tlv);
                return -1;
        }

        if (tlv_get_type(&tlv) == TLV_COMPOUND) {
                real_size = (size_t)tlv_get_length(&tlv) + DAZIBAO_HEADER_SIZE;
        } else {
                real_size = (size_t)tlv_get_length(&tlv);
        }

        path = argv[1];
        fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644);

        if (fd == -1) {
                tlv_destroy(&tlv);
                ERROR("open", -1);
        }

        if (ftruncate(fd, real_size) < 0) {
                fprintf(stderr, "Error while ftruncate path");
                close(fd);
                return -1;
        }

        data = (char*)mmap(NULL, real_size, PROT_WRITE, MAP_SHARED, fd, 0);

        if (data == MAP_FAILED) {
                fprintf(stderr, "Error while mmap ");
                close(fd);
                tlv_destroy(&tlv);
                return -1;
        }

        if (tlv_get_type(&tlv) == TLV_COMPOUND) {
                data[0] = MAGIC_NUMBER;
                memset(data + 1, 0, DAZIBAO_HEADER_SIZE - 1);
                real_size = real_size - DAZIBAO_HEADER_SIZE;
                memcpy(data + DAZIBAO_HEADER_SIZE,
                        tlv_get_value_ptr(&tlv), real_size);
        } else {
                memcpy(data , tlv_get_value_ptr(&tlv), real_size);
        }

        tlv_destroy(&tlv);
        close(fd);
        return 0;
}
Ejemplo n.º 9
0
int action_add(int argc, char **argv, int f_co, int f_dz, int f_d, int f_in,
                char *type, char *daz) {
        dz_t daz_buf;
        unsigned int buff_size_co = 0;
        tlv_t tlv = NULL;
        tlv_t buff_co = NULL;
        tlv_t buff_d = NULL;
        int i,j = 0;

        if (dz_open(&daz_buf, daz, O_RDWR) < 0) {
                fprintf(stderr, "failed open the dazibao\n");
                return -1;
        }

        f_d = (f_d == -1 ? argc : f_d);
        f_co = (f_co == -1 ? argc : f_co);

        for (i = 0; i < argc; i++) {
                int tlv_size = 0;
                /* inizialized tlv */
                if (tlv_init(&tlv) < 0) {
                      printf("error to init tlv\n");
                        return -1;
                }

                /* different possibility to create a standard tlv*/
                if (i == f_in) {
                        tlv_size = tlv_create_input(&tlv, &type[j]);
                        j++;
                } else if (i == f_dz) {
                        tlv_size = dz2tlv(argv[i], &tlv);
                } else {
                        tlv_size = tlv_create_path(argv[i], &tlv, &type[j]);
                        j++;
                }

                /* if not tlv as create error */
                if (tlv_size < 0) {
                        printf("error to create tlv with path %s\n", argv[i]);
                        return -1;
                }

                /* other option who use tlv created */
                if ( i >= f_co ) {
                        /* if tlv to insert to compound it type dated*/
                        if ((i >= f_d) && (f_d > f_co)) {
                                if (tlv_init(&buff_d) < 0) {
                                        printf("error to init tlv compound");
                                        return -1;
                                }
                                tlv_size = tlv_create_date(&buff_d, &tlv,
                                                tlv_size);
                                if (tlv_size < 0) {
                                        printf("error to create tlv dated"
                                                        "%s\n", argv[i]);
                                        return -1;
                                }
                                tlv_destroy(&tlv);
                                tlv = buff_d;
                                buff_d = NULL;
                        }
                        unsigned int size_realloc = TLV_SIZEOF_HEADER;
                        if ((f_co == i) && (tlv_init(&buff_co) < 0)) {
                                printf("error to init tlv compound\n");
                                return -1;
                        }
                        size_realloc += buff_size_co + tlv_size;
                        buff_co = (tlv_t) safe_realloc(buff_co,
                                        sizeof(*buff_co) * size_realloc);
                        if (buff_co == NULL) {
                                ERROR("realloc", -1);
                        }

                        memcpy(buff_co + buff_size_co, tlv, tlv_size);
                        buff_size_co += tlv_size;
                        tlv_destroy(&tlv);

                        /*when all tlv is insert, create tlv compound*/
                        if (i == argc -1) {
                                if (tlv_init(&tlv) < 0) {
                                        printf(" error to init tlv");
                                        return -1;
                                }
                                tlv_size = tlv_create_compound(&tlv, &buff_co,
                                        buff_size_co);
                                if (tlv_size < 0) {
                                        printf(" error to create compound"
                                        " %s\n", argv[i]);
                                        return -1;
                                }
                                tlv_destroy(&buff_co);
                        } else {
                                continue;
                        }
                }

                if ((i >= f_d) && (f_d <= f_co)) {
                        if (tlv_init(&buff_d) < 0) {
                                printf(" error to init tlv dated\n");
                                return -1;
                        }
                        tlv_size = tlv_create_date(&buff_d, &tlv, tlv_size);
                        if (tlv_size < 0) {
                                printf(" error to create tlv dated"
                                        "%s\n", argv[i]);
                                return -1;
                        }
                        tlv_destroy(&tlv);
                        tlv = buff_d;
                        buff_d = NULL;
                }

                if (tlv_size > 0) {
                        if (dz_add_tlv(&daz_buf, &tlv) == -1) {
                                fprintf(stderr, "failed adding the tlv\n");
                                tlv_destroy(&tlv);
                                return -1;
                        }
                        tlv_destroy(&tlv);
                }
        }

        if (dz_close(&daz_buf) < 0) {
                fprintf(stderr, "failed closing the dazibao\n");
                return -1;
        }
        return 0;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
/*
 * 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);
}
Ejemplo n.º 12
0
int cli_print_dz(dz_t *dz, int indent, int lvl, int debug) {

        int status = -1;
        tlv_t tlv;
        off_t off;

        if (tlv_init(&tlv) == -1) {
                LOGERROR("tlv_init");
                return -1;
        }

        while ((off = dz_next_tlv(dz, &tlv)) != EOD) {
                const char *type_str;

                if (off == -1) {
                        LOGERROR("dz_next_tlv failed");
                        goto DESTROY;
                }

                int type = tlv_get_type(&tlv);

                if ((type == TLV_PAD1 || type == TLV_PADN)
                        && !debug) {
                        continue;
                }

                if (type == TLV_LONGH) {
                        dz_set_offset(dz, off);
                        off_t next = cli_print_ltlv(
                                dz, &tlv, indent, lvl, debug);
                        if (next == -1) {
                                LOGERROR("cli_print_ltlv failed");
                                goto DESTROY;
                        }
                        dz_set_offset(dz, off + next);
                        continue;
                }

                for (int i = 0; i <= indent; i++) {
                        printf("--");
                }

                int len = tlv_get_length(&tlv);

                type_str = tlv_type2str(type);
                printf(" @[%10li]: %8s (%d bytes)\n", (unsigned long)off,
                        (type_str ? type_str : "unknown"), len);


                if ((type != TLV_DATED && type != TLV_COMPOUND) || lvl == 0) {
                        continue;
                }

                dz_t cmpnd = { -1,
                               0,
                               (off + TLV_SIZEOF_HEADER + len),
                               (off + TLV_SIZEOF_HEADER
                                       + (type == TLV_DATED ?
                                               TLV_SIZEOF_DATE : 0)),
                               -1,
                               dz->data};

                if (cli_print_dz(&cmpnd, indent + 1, lvl - 1, debug)) {
                        goto DESTROY;
                }
        }

        /* If no error occurred */
        status = 0;

DESTROY:
        if (tlv_destroy(&tlv) != 0) {
                LOGERROR("tlv_destroy failed");
                status = -1;
        }
        return status;
}
Ejemplo n.º 13
0
int cli_extract_tlv(dz_t *dz, off_t offset, int name_mod) {

        tlv_t tlv;
        int status = -1;
        int out_fd;
        int type;

        if (tlv_init(&tlv) != 0) {
                LOGERROR("Failed initializing TLV.");
                goto OUT;
        }

        switch (dz_tlv_at(dz, &tlv, offset)) {
        case -1:
        case EOD:
                LOGERROR("dz_tlv_at %d failed.", (int)offset);
                goto DESTROY;
        };

        type = tlv_get_type(&tlv);

        switch (type) {
        case TLV_DATED:
        case TLV_COMPOUND: {
                int len = tlv_get_length(&tlv);
                dz_t cmpnd = { -1,
                               0,
                               (offset + TLV_SIZEOF_HEADER
                                       + len),
                               (offset + TLV_SIZEOF_HEADER
                                       + (type == TLV_DATED ?
                                               TLV_SIZEOF_DATE : 0)),
                               -1,
                               dz->data};

                if (cli_extract_all(&cmpnd, offset + name_mod) != 0) {
                        goto DESTROY;
                }
                break;
        };
        case TLV_LONGH:
                if (cli_extract_ltlv(dz, &tlv, offset, name_mod) != 0) {
                        LOGERROR("cli_extract_ltlv failed");
                        goto DESTROY;
                }
                break;
        default:
                if (dz_read_tlv(dz, &tlv, offset) != 0) {
                        LOGERROR("dz_read_tlv failed");
                        goto DESTROY;
                }
                if (cli_write_file(tlv_get_value_ptr(&tlv),
                                        tlv_get_length(&tlv),
                                        offset + name_mod,
                                        type) == -1) {
                        LOGERROR("Printing in file failed.");
                        goto DESTROY;
                }
        };

        /* If no error occurred */
        status = 0;

DESTROY:
        if (tlv_destroy(&tlv) != 0) {
                LOGERROR("tlv_destroy failed");
                status = -1;
        }

OUT:
        return status;
}
Ejemplo n.º 14
0
int cli_add(int argc, char **argv) {

        int status = -1;
        dz_t dz;
        tlv_t tlv;
        char date = 0;
        char *type = NULL;
        char *file;
        char **inputs;
        int nb_inputs = 0;
        /* Parsing arguments. */

        struct s_option opt[] = {
                {"--date", ARG_TYPE_FLAG, (void *)&date},
                {"--type", ARG_TYPE_STRING, (void *)&type},
        };

        struct s_args args = {&nb_inputs, &inputs, opt};

        if (jparse_args(argc, argv, &args, sizeof(opt)/sizeof(*opt)) == -1) {
                LOGERROR("jparse_args failed.");
                goto OUT;
        }

        if (nb_inputs < 2) {
                LOGERROR("Missing parameters (see manual).");
                goto OUT;
        }

        file = inputs[--nb_inputs];

        if (dz_open(&dz, file, O_RDWR) != 0) {
                LOGERROR("Failed opening %s.", file);
                goto OUT;
        }

        if (tlv_init(&tlv) == -1) {
                LOGERROR("tlv_init failed.");
                goto CLOSE;
        }

        if (cli_mk_tlv(&tlv, nb_inputs, inputs, type, date) == -1) {
                LOGERROR("cli_mk_tlv failed.");
                goto DESTROY;
        }


        if (dz_add_tlv(&dz, &tlv) != 0) {
                LOGERROR("Failed adding TLV.");
                goto DESTROY;
        }

        /* If no error occurred */
        status = 0;

DESTROY:
        if (tlv_destroy(&tlv) != 0) {
                LOGERROR("tlv_destroy failed");
                status = -1;
        }

CLOSE:
        if (dz_close(&dz) == -1) {
                LOGERROR("Failed closing dazibao.");
                status = -1;
        }

OUT:
        return status;
}