diff --git a/agent/agent.h b/agent/agent.h index de0d25fb3..e2d2df4ee 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -451,7 +451,8 @@ int agent_pk_get_algo (gcry_sexp_t s_key); int agent_key_available (const unsigned char *grip); gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, int *r_keytype, - unsigned char **r_shadow_info); + unsigned char **r_shadow_info, + unsigned char **r_shadow_info_type); gpg_error_t agent_delete_key (ctrl_t ctrl, const char *desc_text, const unsigned char *grip, int force, int only_stubs); @@ -535,8 +536,15 @@ unsigned char *make_shadow_info (const char *serialno, const char *idstring); int agent_shadow_key (const unsigned char *pubkey, const unsigned char *shadow_info, unsigned char **result); +int agent_shadow_key_type (const unsigned char *pubkey, + const unsigned char *shadow_info, + const unsigned char *type, + unsigned char **result); gpg_error_t agent_get_shadow_info (const unsigned char *shadowkey, unsigned char const **shadow_info); +gpg_error_t agent_get_shadow_info_type (const unsigned char *shadowkey, + unsigned char const **shadow_info, + unsigned char **shadow_type); gpg_error_t parse_shadow_info (const unsigned char *shadow_info, char **r_hexsn, char **r_idstr, int *r_pinlen); gpg_error_t s2k_hash_passphrase (const char *passphrase, int hashalgo, diff --git a/agent/command.c b/agent/command.c index d374fd06f..0430745e4 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1198,6 +1198,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, char *fpr = NULL; int keytype; unsigned char *shadow_info = NULL; + unsigned char *shadow_info_type = NULL; char *serialno = NULL; char *idstr = NULL; const char *keytypestr; @@ -1208,7 +1209,8 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, char ttlbuf[20]; char flagsbuf[5]; - err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info); + err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info, + &shadow_info_type); if (err) { if (in_ssh && gpg_err_code (err) == GPG_ERR_NOT_FOUND) @@ -1280,9 +1282,18 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, if (shadow_info) { - err = parse_shadow_info (shadow_info, &serialno, &idstr, NULL); - if (err) - goto leave; + if (strcmp (shadow_info_type, "t1-v1") == 0) + { + err = parse_shadow_info (shadow_info, &serialno, &idstr, NULL); + if (err) + goto leave; + } + else + { + log_error ("unrecognised shadow key type %s\n", shadow_info_type); + err = GPG_ERR_BAD_KEY; + goto leave; + } } if (!data) @@ -1317,6 +1328,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, leave: xfree (fpr); + xfree (shadow_info_type); xfree (shadow_info); xfree (serialno); xfree (idstr); diff --git a/agent/findkey.c b/agent/findkey.c index 1494615c4..0951a754e 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -1320,7 +1320,8 @@ agent_key_available (const unsigned char *grip) S-expression. */ gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, - int *r_keytype, unsigned char **r_shadow_info) + int *r_keytype, unsigned char **r_shadow_info, + unsigned char **r_shadow_info_type) { gpg_error_t err; unsigned char *buf; @@ -1367,7 +1368,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, const unsigned char *s; size_t n; - err = agent_get_shadow_info (buf, &s); + err = agent_get_shadow_info_type (buf, &s, r_shadow_info_type); if (!err) { n = gcry_sexp_canon_len (s, 0, NULL, NULL); diff --git a/agent/protect.c b/agent/protect.c index e3bbf3ed5..54666e717 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -1516,9 +1516,10 @@ make_shadow_info (const char *serialno, const char *idstring) to. The input parameters are expected to be valid canonicalized S-expressions */ int -agent_shadow_key (const unsigned char *pubkey, - const unsigned char *shadow_info, - unsigned char **result) +agent_shadow_key_type (const unsigned char *pubkey, + const unsigned char *shadow_info, + const unsigned char *type, + unsigned char **result) { const unsigned char *s; const unsigned char *point; @@ -1574,7 +1575,7 @@ agent_shadow_key (const unsigned char *pubkey, log_assert (depth == 1); /* Calculate required length by taking in account: the "shadowed-" - prefix, the "shadowed", "t1-v1" as well as some parenthesis */ + prefix, the "shadowed", shadow type as well as some parenthesis */ n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1; *result = xtrymalloc (n); p = (char*)*result; @@ -1584,7 +1585,7 @@ agent_shadow_key (const unsigned char *pubkey, /* (10:public-key ...)*/ memcpy (p, pubkey+14, point - (pubkey+14)); p += point - (pubkey+14); - p = stpcpy (p, "(8:shadowed5:t1-v1"); + p += sprintf (p, "(8:shadowed%d:%s", (int)strlen(type), type); memcpy (p, shadow_info, shadow_info_len); p += shadow_info_len; *p++ = ')'; @@ -1594,11 +1595,20 @@ agent_shadow_key (const unsigned char *pubkey, return 0; } +int +agent_shadow_key (const unsigned char *pubkey, + const unsigned char *shadow_info, + unsigned char **result) +{ + return agent_shadow_key_type (pubkey, shadow_info, "t1-v1", result); +} + /* Parse a canonical encoded shadowed key and return a pointer to the - inner list with the shadow_info */ + inner list with the shadow_info and the shadow type */ gpg_error_t -agent_get_shadow_info (const unsigned char *shadowkey, - unsigned char const **shadow_info) +agent_get_shadow_info_type (const unsigned char *shadowkey, + unsigned char const **shadow_info, + unsigned char **shadow_type) { const unsigned char *s; size_t n; @@ -1650,17 +1660,59 @@ agent_get_shadow_info (const unsigned char *shadowkey, n = snext (&s); if (!n) return gpg_error (GPG_ERR_INV_SEXP); - if (smatch (&s, n, "t1-v1")) + if (shadow_type) { + char *buf = xtrymalloc(n+1); + memcpy(buf, s, n); + buf[n] = '\0'; + *shadow_type = buf; + } + + if (smatch (&s, n, "t1-v1") || smatch(&s, n, "tpm2-v1")) { if (*s != '(') return gpg_error (GPG_ERR_INV_SEXP); - *shadow_info = s; + if (shadow_info) + *shadow_info = s; } else return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); return 0; } +gpg_error_t +agent_get_shadow_info(const unsigned char *shadowkey, + unsigned char const **shadow_info) +{ + return agent_get_shadow_info_type(shadowkey, shadow_info, NULL); +} + +int +agent_is_tpm2_key(gcry_sexp_t s_skey) +{ + unsigned char *buf; + unsigned char *type; + size_t len; + gpg_error_t err; + + err = make_canon_sexp(s_skey, &buf, &len); + if (err) + return 0; + + err = agent_get_shadow_info_type(buf, NULL, &type); + if (err) + return 0; + + err = strcmp(type, "tpm2-v1") == 0; + xfree(type); + return err; +} + +gpg_error_t +agent_get_shadow_type(const unsigned char *shadowkey, + unsigned char **shadow_type) +{ + return agent_get_shadow_info_type(shadowkey, NULL, shadow_type); +} /* Parse the canonical encoded SHADOW_INFO S-expression. On success the hex encoded serial number is returned as a malloced strings at