diff --git a/src/cbor.c b/src/cbor.c index ab99b34d..e6d68823 100644 --- a/src/cbor.c +++ b/src/cbor.c @@ -1386,12 +1386,27 @@ cbor_decode_assert_authdata(const cbor_item_t *item, fido_blob_t *authdata_cbor, static int decode_x5c(const cbor_item_t *item, void *arg) { - fido_blob_t *x5c = arg; + fido_blob_t *list_ptr; + fido_blob_t x5c_blob; + fido_blob_array_t *x5c = arg; - if (x5c->len) - return (0); /* ignore */ + memset(&x5c_blob, 0, sizeof(x5c_blob)); - return (fido_blob_decode(item, x5c)); + if (fido_blob_decode(item, &x5c_blob) < 0) { + fido_log_debug("%s: fido_blob_decode", __func__); + return (-1); + } + + if ((list_ptr = recallocarray(x5c->ptr, x5c->len, + x5c->len + 1, sizeof(x5c_blob))) == NULL) { + fido_blob_reset(&x5c_blob); + return (-1); + } + + list_ptr[x5c->len++] = x5c_blob; + x5c->ptr = list_ptr; + + return (0); } static int diff --git a/src/cred.c b/src/cred.c index 4a7a7257..b37937f4 100644 --- a/src/cred.c +++ b/src/cred.c @@ -284,15 +284,20 @@ verify_attstmt(const fido_blob_t *dgst, const fido_attstmt_t *attstmt) EVP_PKEY *pkey = NULL; int ok = -1; - /* openssl needs ints */ - if (attstmt->x5c.len > INT_MAX) { + if (!attstmt->x5c.len) { fido_log_debug("%s: x5c.len=%zu", __func__, attstmt->x5c.len); return (-1); } + /* openssl needs ints */ + if (attstmt->x5c.ptr[0].len > INT_MAX) { + fido_log_debug("%s: x5c[0].len=%zu", __func__, attstmt->x5c.ptr[0].len); + return (-1); + } + /* fetch key from x509 */ - if ((rawcert = BIO_new_mem_buf(attstmt->x5c.ptr, - (int)attstmt->x5c.len)) == NULL || + if ((rawcert = BIO_new_mem_buf(attstmt->x5c.ptr[0].ptr, + (int)attstmt->x5c.ptr[0].len)) == NULL || (cert = d2i_X509_bio(rawcert, NULL)) == NULL || (pkey = X509_get_pubkey(cert)) == NULL) { fido_log_debug("%s: x509 key", __func__); @@ -543,7 +548,7 @@ fido_cred_clean_attstmt(fido_attstmt_t *attstmt) fido_blob_reset(&attstmt->certinfo); fido_blob_reset(&attstmt->pubarea); fido_blob_reset(&attstmt->cbor); - fido_blob_reset(&attstmt->x5c); + fido_free_blob_array(&attstmt->x5c); fido_blob_reset(&attstmt->sig); memset(attstmt, 0, sizeof(*attstmt)); @@ -688,9 +693,23 @@ fido_cred_set_id(fido_cred_t *cred, const unsigned char *ptr, size_t len) int fido_cred_set_x509(fido_cred_t *cred, const unsigned char *ptr, size_t len) { - if (fido_blob_set(&cred->attstmt.x5c, ptr, len) < 0) + fido_blob_t x5c_blob; + fido_blob_t *list_ptr; + + fido_free_blob_array(&cred->attstmt.x5c); + + if (fido_blob_set(&x5c_blob, ptr, len) < 0) return (FIDO_ERR_INVALID_ARGUMENT); + if ((list_ptr = recallocarray(cred->attstmt.x5c.ptr, cred->attstmt.x5c.len, + cred->attstmt.x5c.len + 1, sizeof(x5c_blob))) == NULL) { + fido_blob_reset(&x5c_blob); + return (-1); + } + + list_ptr[cred->attstmt.x5c.len++] = x5c_blob; + cred->attstmt.x5c.ptr = list_ptr; + return (FIDO_OK); } @@ -1030,15 +1049,39 @@ fido_cred_clientdata_hash_len(const fido_cred_t *cred) const unsigned char * fido_cred_x5c_ptr(const fido_cred_t *cred) { - return (cred->attstmt.x5c.ptr); + return (fido_cred_x5c_list_ptr(cred, 0)); } size_t fido_cred_x5c_len(const fido_cred_t *cred) +{ + return (fido_cred_x5c_list_len(cred, 0)); +} + +size_t +fido_cred_x5c_list_count(const fido_cred_t *cred) { return (cred->attstmt.x5c.len); } +const unsigned char * +fido_cred_x5c_list_ptr(const fido_cred_t *cred, size_t i) +{ + if (i >= cred->attstmt.x5c.len) + return (NULL); + + return (cred->attstmt.x5c.ptr[i].ptr); +} + +size_t +fido_cred_x5c_list_len(const fido_cred_t *cred, size_t i) +{ + if (i >= cred->attstmt.x5c.len) + return (0); + + return (cred->attstmt.x5c.ptr[i].len); +} + const unsigned char * fido_cred_sig_ptr(const fido_cred_t *cred) { diff --git a/src/export.gnu b/src/export.gnu index ea6ca7d3..8fcb6d4d 100644 --- a/src/export.gnu +++ b/src/export.gnu @@ -196,6 +196,9 @@ fido_cred_verify; fido_cred_verify_self; fido_cred_x5c_len; + fido_cred_x5c_list_count; + fido_cred_x5c_list_len; + fido_cred_x5c_list_ptr; fido_cred_x5c_ptr; fido_dev_build; fido_dev_cancel; diff --git a/src/fido.h b/src/fido.h index 914e3776..79b31112 100644 --- a/src/fido.h +++ b/src/fido.h @@ -124,6 +124,7 @@ const unsigned char *fido_cred_pubkey_ptr(const fido_cred_t *); const unsigned char *fido_cred_sig_ptr(const fido_cred_t *); const unsigned char *fido_cred_user_id_ptr(const fido_cred_t *); const unsigned char *fido_cred_x5c_ptr(const fido_cred_t *); +const unsigned char *fido_cred_x5c_list_ptr(const fido_cred_t *, size_t); int fido_assert_allow_cred(fido_assert_t *, const unsigned char *, size_t); int fido_assert_empty_allow_list(fido_assert_t *); @@ -226,6 +227,8 @@ size_t fido_cred_pubkey_len(const fido_cred_t *); size_t fido_cred_sig_len(const fido_cred_t *); size_t fido_cred_user_id_len(const fido_cred_t *); size_t fido_cred_x5c_len(const fido_cred_t *); +size_t fido_cred_x5c_list_count(const fido_cred_t *); +size_t fido_cred_x5c_list_len(const fido_cred_t *, size_t); uint8_t fido_assert_flags(const fido_assert_t *, size_t); uint32_t fido_assert_sigcount(const fido_assert_t *, size_t); diff --git a/src/fido/types.h b/src/fido/types.h index 01d68200..0aaa8cb6 100644 --- a/src/fido/types.h +++ b/src/fido/types.h @@ -140,12 +140,12 @@ typedef struct fido_attcred { } fido_attcred_t; typedef struct fido_attstmt { - fido_blob_t certinfo; /* tpm attestation TPMS_ATTEST structure */ - fido_blob_t pubarea; /* tpm attestation TPMT_PUBLIC structure */ - fido_blob_t cbor; /* cbor-encoded attestation statement */ - fido_blob_t x5c; /* attestation certificate */ - fido_blob_t sig; /* attestation signature */ - int alg; /* attestation algorithm (cose) */ + fido_blob_t certinfo; /* tpm attestation TPMS_ATTEST structure */ + fido_blob_t pubarea; /* tpm attestation TPMT_PUBLIC structure */ + fido_blob_t cbor; /* cbor-encoded attestation statement */ + fido_blob_array_t x5c; /* attestation certificate chain */ + fido_blob_t sig; /* attestation signature */ + int alg; /* attestation algorithm (cose) */ } fido_attstmt_t; typedef struct fido_rp {