Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sc-hsm-tool: Add options for public key authentication #1711

Closed
wants to merge 23 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
sc-hsm-tool: use goto for error handling
  • Loading branch information
Frank Braun committed Oct 29, 2019
commit 953b64f2d93b171ad477272aee938fd33f4d2ca9
91 changes: 50 additions & 41 deletions src/tools/sc-hsm-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1702,8 +1702,8 @@ static int export_key(sc_card_t *card, int keyid, const char *outf)
u8 dev_aut_cert[MAX_CERT];
u8 dica[MAX_CERT];
u8 tag = SC_ASN1_TAG_CONSTRUCTED | SC_ASN1_TAG_SEQUENCE; /* 0x30 */
int r, ef_cert_len, dev_aut_cert_len, dica_len, total_certs_len;
u8 *data, *out, *ptr;
int r = 0, ef_cert_len, dev_aut_cert_len, dica_len, total_certs_len;
u8 *data = NULL, *out = NULL, *ptr;
size_t datalen, outlen;

if ((keyid < 1) || (keyid > 255)) {
Expand Down Expand Up @@ -1769,44 +1769,46 @@ static int export_key(sc_card_t *card, int keyid, const char *outf)
outlen = 8 + datalen;
if (!(data = malloc(datalen))) {
fprintf(stderr, "Malloc failed\n");
return -1;
r = -1;
goto err;
}
if (!(out = malloc(outlen))) {
fprintf(stderr, "Malloc failed\n");
free(data);
return -1;
r = -1;
goto err;
}
memcpy(data, ef_cert, ef_cert_len);
memcpy(data + ef_cert_len, dev_aut_cert, dev_aut_cert_len);
memcpy(data + ef_cert_len + dev_aut_cert_len, dica, dica_len);

if ((r = sc_asn1_put_tag(tag, data, datalen, out, outlen, &ptr)) < 0) {
fprintf(stderr, "Error formatting ASN1 sequence: %s\n", sc_strerror(r));
free(out);
free(data);
return -1;
r = -1;
goto err;
}
outlen = ptr - out;

if (!(outfp = fopen(outf, "wb"))) {
perror(outf);
free(out);
free(data);
return -1;
r = -1;
goto err;
}

if (fwrite(out, 1, outlen, outfp) != (size_t)outlen) {
perror(outf);
r = -1;
goto err;
}

err:
if (outfp)
fclose(outfp);
if (out)
free(out);
if (data)
free(data);
return -1;
}

fclose(outfp);
free(out);
free(data);
return 0;
return r;
}

static void get_CHR(char *chrstr, int is_cvc, sc_context_t *ctx, const u8 *buf, size_t buflen)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use sc_pkcs15emu_sc_hsm_decode_cvc for parsing

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding EF_C_DevAut I can see that it is set in the static function sc_hsm_perform_chip_authentication(). sc_hsm_perform_chip_authentication() is only called from sc_hsm_pin_cmd(). That is, filling EF_C_DevAut currently requires PIN entry, which is not necessary for my implementation.

What would be a good way to use EF_C_DevAut, ideally without PIN entry?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding sc_pkcs15emu_sc_hsm_decode_cvc(): I spent many hours trying to get it to work.
Like I wrote in #1711 (comment), I wasn't able to parse the device certificate and the device issuer certificate with it. For the public key, sc_cvc_t.car is filled correctly, but sc_cvc_t.outer_car contains garbage. Unfortunately, I couldn't figure out what the problem is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be a good way to use EF_C_DevAut, ideally without PIN entry?

The basic idea is in sc-hsm-tool to

  1. force a sc-hsm card driver, as done here and
  2. then cast card->drv_data to struct sc_hsm_private_data * and use its EF_C_DevAut if it's available.

Additionally, you may want to transfer ownership of a newly read EF_C_DevAut to the driver for re-use. You don't need to perform CA to do this.

Expand Down Expand Up @@ -1882,63 +1884,64 @@ static int register_public_key_with_card(sc_context_t *ctx, sc_card_t *card, con

static int register_public_key(sc_context_t *ctx, sc_card_t *card, const char *inf)
{
FILE *in;
FILE *in = NULL;
struct stat sb;
u8 *pka;
u8 *pka = NULL;
u8 tag = SC_ASN1_TAG_CONSTRUCTED | SC_ASN1_TAG_SEQUENCE; /* 0x30 */
unsigned int cla_out, tag_out;
const u8 *buf;
const u8 *pk;
const u8 *devcert;
const u8 *dicacert;
size_t taglen, pk_len, devcert_len, dicacert_len;
int r;
int r = 0;

if (!(in = fopen(inf, "rb"))) {
frankbraun marked this conversation as resolved.
Show resolved Hide resolved
perror(inf);
return -1;
r = -1;
goto err;
}
if (fstat(fileno(in), &sb)) {
perror("cannot fstat");
fclose(in);
return -1;
r = -1;
goto err;
}
if (sb.st_size == 0) {
fprintf(stderr, "File is empty\n");
fclose(in);
return -1;
r = -1;
goto err;
}
if (!(pka = malloc(sb.st_size))) {
fprintf(stderr, "Malloc failed\n");
fclose(in);
return -1;
r = -1;
goto err;
}
if (fread(pka, 1, sb.st_size, in) != (size_t)sb.st_size) {
perror(inf);
free(pka);
fclose(in);
return -1;
r = -1;
goto err;
}
fclose(in);
in = NULL;
if (pka[0] != tag) {
fprintf(stderr, "File does not contain a public key with certificates\n");
free(pka);
return -1;
r = -1;
goto err;
}

/* read ASN.1 sequence */
buf = pka;
if ((r = sc_asn1_read_tag(&buf, sb.st_size, &cla_out, &tag_out, &taglen)) < 0) {
fprintf(stderr, "Error reading ASN.1 sequence: %s\n", sc_strerror(r));
free(pka);
return -1;
r = -1;
goto err;
}

/* read public key */
if ((r = sc_asn1_read_tag(&buf, sb.st_size, &cla_out, &tag_out, &taglen)) < 0) {
frankbraun marked this conversation as resolved.
Show resolved Hide resolved
fprintf(stderr, "Error reading ASN.1 sequence: %s\n", sc_strerror(r));
free(pka);
return -1;
r = -1;
goto err;
}
pk = buf;
pk_len = taglen;
Expand All @@ -1947,8 +1950,8 @@ static int register_public_key(sc_context_t *ctx, sc_card_t *card, const char *i
/* read device certificate */
if ((r = sc_asn1_read_tag(&buf, sb.st_size, &cla_out, &tag_out, &taglen)) < 0) {
fprintf(stderr, "Error reading ASN.1 sequence: %s\n", sc_strerror(r));
free(pka);
return -1;
r = -1;
goto err;
}
devcert = buf;
devcert_len = taglen;
Expand All @@ -1957,14 +1960,20 @@ static int register_public_key(sc_context_t *ctx, sc_card_t *card, const char *i
/* read device CA */
if ((r = sc_asn1_read_tag(&buf, sb.st_size, &cla_out, &tag_out, &taglen)) < 0) {
frankbraun marked this conversation as resolved.
Show resolved Hide resolved
fprintf(stderr, "Error reading ASN.1 sequence: %s\n", sc_strerror(r));
free(pka);
return -1;
r = -1;
goto err;
}
dicacert = buf;
dicacert_len = taglen;

r = register_public_key_with_card(ctx, card, pk, pk_len, devcert, devcert_len, dicacert, dicacert_len);
free(pka);

err:
if (pka)
free(pka);
if (in)
fclose(in);

return r;
}

Expand Down