summaryrefslogtreecommitdiff
path: root/src/cred.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cred.c')
-rw-r--r--src/cred.c122
1 files changed, 52 insertions, 70 deletions
diff --git a/src/cred.c b/src/cred.c
index c4e1edb..4ecbba8 100644
--- a/src/cred.c
+++ b/src/cred.c
@@ -76,8 +76,8 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
76 } 76 }
77 77
78 /* extensions */ 78 /* extensions */
79 if (cred->ext) 79 if (cred->ext.mask)
80 if ((argv[5] = cbor_encode_extensions(cred->ext)) == NULL) { 80 if ((argv[5] = cbor_encode_extensions(&cred->ext)) == NULL) {
81 fido_log_debug("%s: cbor_encode_extensions", __func__); 81 fido_log_debug("%s: cbor_encode_extensions", __func__);
82 r = FIDO_ERR_INTERNAL; 82 r = FIDO_ERR_INTERNAL;
83 goto fail; 83 goto fail;
@@ -106,8 +106,8 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
106 } 106 }
107 107
108 /* framing and transmission */ 108 /* framing and transmission */
109 if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, 9, &f) < 0 || 109 if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 ||
110 fido_tx(dev, CTAP_FRAME_INIT | CTAP_CMD_CBOR, f.ptr, f.len) < 0) { 110 fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
111 fido_log_debug("%s: fido_tx", __func__); 111 fido_log_debug("%s: fido_tx", __func__);
112 r = FIDO_ERR_TX; 112 r = FIDO_ERR_TX;
113 goto fail; 113 goto fail;
@@ -126,14 +126,14 @@ fail:
126static int 126static int
127fido_dev_make_cred_rx(fido_dev_t *dev, fido_cred_t *cred, int ms) 127fido_dev_make_cred_rx(fido_dev_t *dev, fido_cred_t *cred, int ms)
128{ 128{
129 const uint8_t cmd = CTAP_FRAME_INIT | CTAP_CMD_CBOR; 129 unsigned char reply[FIDO_MAXMSG];
130 unsigned char reply[2048];
131 int reply_len; 130 int reply_len;
132 int r; 131 int r;
133 132
134 fido_cred_reset_rx(cred); 133 fido_cred_reset_rx(cred);
135 134
136 if ((reply_len = fido_rx(dev, cmd, &reply, sizeof(reply), ms)) < 0) { 135 if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
136 ms)) < 0) {
137 fido_log_debug("%s: fido_rx", __func__); 137 fido_log_debug("%s: fido_rx", __func__);
138 return (FIDO_ERR_RX); 138 return (FIDO_ERR_RX);
139 } 139 }
@@ -170,7 +170,8 @@ int
170fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin) 170fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
171{ 171{
172 if (fido_dev_is_fido2(dev) == false) { 172 if (fido_dev_is_fido2(dev) == false) {
173 if (pin != NULL || cred->rk == FIDO_OPT_TRUE || cred->ext != 0) 173 if (pin != NULL || cred->rk == FIDO_OPT_TRUE ||
174 cred->ext.mask != 0)
174 return (FIDO_ERR_UNSUPPORTED_OPTION); 175 return (FIDO_ERR_UNSUPPORTED_OPTION);
175 return (u2f_register(dev, cred, -1)); 176 return (u2f_register(dev, cred, -1));
176 } 177 }
@@ -179,15 +180,9 @@ fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
179} 180}
180 181
181static int 182static int
182check_extensions(int authdata_ext, int ext) 183check_extensions(const fido_cred_ext_t *authdata_ext, const fido_cred_ext_t *ext)
183{ 184{
184 if (authdata_ext != ext) { 185 return (timingsafe_bcmp(authdata_ext, ext, sizeof(*authdata_ext)));
185 fido_log_debug("%s: authdata_ext=0x%x != ext=0x%x", __func__,
186 authdata_ext, ext);
187 return (-1);
188 }
189
190 return (0);
191} 186}
192 187
193int 188int
@@ -208,48 +203,6 @@ fido_check_rp_id(const char *id, const unsigned char *obtained_hash)
208} 203}
209 204
210static int 205static int
211get_signed_hash_packed(fido_blob_t *dgst, const fido_blob_t *clientdata,
212 const fido_blob_t *authdata_cbor)
213{
214 cbor_item_t *item = NULL;
215 unsigned char *authdata_ptr = NULL;
216 size_t authdata_len;
217 struct cbor_load_result cbor;
218 SHA256_CTX ctx;
219 int ok = -1;
220
221 if ((item = cbor_load(authdata_cbor->ptr, authdata_cbor->len,
222 &cbor)) == NULL) {
223 fido_log_debug("%s: cbor_load", __func__);
224 goto fail;
225 }
226
227 if (cbor_isa_bytestring(item) == false ||
228 cbor_bytestring_is_definite(item) == false) {
229 fido_log_debug("%s: cbor type", __func__);
230 goto fail;
231 }
232
233 authdata_ptr = cbor_bytestring_handle(item);
234 authdata_len = cbor_bytestring_length(item);
235
236 if (dgst->len != SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 ||
237 SHA256_Update(&ctx, authdata_ptr, authdata_len) == 0 ||
238 SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 ||
239 SHA256_Final(dgst->ptr, &ctx) == 0) {
240 fido_log_debug("%s: sha256", __func__);
241 goto fail;
242 }
243
244 ok = 0;
245fail:
246 if (item != NULL)
247 cbor_decref(&item);
248
249 return (ok);
250}
251
252static int
253get_signed_hash_u2f(fido_blob_t *dgst, const unsigned char *rp_id, 206get_signed_hash_u2f(fido_blob_t *dgst, const unsigned char *rp_id,
254 size_t rp_id_len, const fido_blob_t *clientdata, const fido_blob_t *id, 207 size_t rp_id_len, const fido_blob_t *clientdata, const fido_blob_t *id,
255 const es256_pk_t *pk) 208 const es256_pk_t *pk)
@@ -356,16 +309,16 @@ fido_cred_verify(const fido_cred_t *cred)
356 goto out; 309 goto out;
357 } 310 }
358 311
359 if (check_extensions(cred->authdata_ext, cred->ext) < 0) { 312 if (check_extensions(&cred->authdata_ext, &cred->ext) != 0) {
360 fido_log_debug("%s: check_extensions", __func__); 313 fido_log_debug("%s: check_extensions", __func__);
361 r = FIDO_ERR_INVALID_PARAM; 314 r = FIDO_ERR_INVALID_PARAM;
362 goto out; 315 goto out;
363 } 316 }
364 317
365 if (!strcmp(cred->fmt, "packed")) { 318 if (!strcmp(cred->fmt, "packed")) {
366 if (get_signed_hash_packed(&dgst, &cred->cdh, 319 if (fido_get_signed_hash(COSE_ES256, &dgst, &cred->cdh,
367 &cred->authdata_cbor) < 0) { 320 &cred->authdata_cbor) < 0) {
368 fido_log_debug("%s: get_signed_hash_packed", __func__); 321 fido_log_debug("%s: fido_get_signed_hash", __func__);
369 r = FIDO_ERR_INTERNAL; 322 r = FIDO_ERR_INTERNAL;
370 goto out; 323 goto out;
371 } 324 }
@@ -395,7 +348,7 @@ out:
395int 348int
396fido_cred_verify_self(const fido_cred_t *cred) 349fido_cred_verify_self(const fido_cred_t *cred)
397{ 350{
398 unsigned char buf[SHA256_DIGEST_LENGTH]; 351 unsigned char buf[1024]; /* XXX */
399 fido_blob_t dgst; 352 fido_blob_t dgst;
400 int ok = -1; 353 int ok = -1;
401 int r; 354 int r;
@@ -431,16 +384,16 @@ fido_cred_verify_self(const fido_cred_t *cred)
431 goto out; 384 goto out;
432 } 385 }
433 386
434 if (check_extensions(cred->authdata_ext, cred->ext) < 0) { 387 if (check_extensions(&cred->authdata_ext, &cred->ext) != 0) {
435 fido_log_debug("%s: check_extensions", __func__); 388 fido_log_debug("%s: check_extensions", __func__);
436 r = FIDO_ERR_INVALID_PARAM; 389 r = FIDO_ERR_INVALID_PARAM;
437 goto out; 390 goto out;
438 } 391 }
439 392
440 if (!strcmp(cred->fmt, "packed")) { 393 if (!strcmp(cred->fmt, "packed")) {
441 if (get_signed_hash_packed(&dgst, &cred->cdh, 394 if (fido_get_signed_hash(cred->attcred.type, &dgst, &cred->cdh,
442 &cred->authdata_cbor) < 0) { 395 &cred->authdata_cbor) < 0) {
443 fido_log_debug("%s: get_signed_hash_packed", __func__); 396 fido_log_debug("%s: fido_get_signed_hash", __func__);
444 r = FIDO_ERR_INTERNAL; 397 r = FIDO_ERR_INTERNAL;
445 goto out; 398 goto out;
446 } 399 }
@@ -519,9 +472,9 @@ fido_cred_reset_tx(fido_cred_t *cred)
519 memset(&cred->rp, 0, sizeof(cred->rp)); 472 memset(&cred->rp, 0, sizeof(cred->rp));
520 memset(&cred->user, 0, sizeof(cred->user)); 473 memset(&cred->user, 0, sizeof(cred->user));
521 memset(&cred->excl, 0, sizeof(cred->excl)); 474 memset(&cred->excl, 0, sizeof(cred->excl));
475 memset(&cred->ext, 0, sizeof(cred->ext));
522 476
523 cred->type = 0; 477 cred->type = 0;
524 cred->ext = 0;
525 cred->rk = FIDO_OPT_OMIT; 478 cred->rk = FIDO_OPT_OMIT;
526 cred->uv = FIDO_OPT_OMIT; 479 cred->uv = FIDO_OPT_OMIT;
527} 480}
@@ -810,10 +763,14 @@ fail:
810int 763int
811fido_cred_set_extensions(fido_cred_t *cred, int ext) 764fido_cred_set_extensions(fido_cred_t *cred, int ext)
812{ 765{
813 if (ext != 0 && ext != FIDO_EXT_HMAC_SECRET) 766 if (ext == 0)
814 return (FIDO_ERR_INVALID_ARGUMENT); 767 cred->ext.mask = 0;
815 768 else {
816 cred->ext = ext; 769 if (ext != FIDO_EXT_HMAC_SECRET &&
770 ext != FIDO_EXT_CRED_PROTECT)
771 return (FIDO_ERR_INVALID_ARGUMENT);
772 cred->ext.mask |= ext;
773 }
817 774
818 return (FIDO_OK); 775 return (FIDO_OK);
819} 776}
@@ -844,6 +801,25 @@ fido_cred_set_uv(fido_cred_t *cred, fido_opt_t uv)
844} 801}
845 802
846int 803int
804fido_cred_set_prot(fido_cred_t *cred, int prot)
805{
806 if (prot == 0) {
807 cred->ext.mask &= ~FIDO_EXT_CRED_PROTECT;
808 cred->ext.prot = 0;
809 } else {
810 if (prot != FIDO_CRED_PROT_UV_OPTIONAL &&
811 prot != FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID &&
812 prot != FIDO_CRED_PROT_UV_REQUIRED)
813 return (FIDO_ERR_INVALID_ARGUMENT);
814
815 cred->ext.mask |= FIDO_EXT_CRED_PROTECT;
816 cred->ext.prot = prot;
817 }
818
819 return (FIDO_OK);
820}
821
822int
847fido_cred_set_fmt(fido_cred_t *cred, const char *fmt) 823fido_cred_set_fmt(fido_cred_t *cred, const char *fmt)
848{ 824{
849 free(cred->fmt); 825 free(cred->fmt);
@@ -991,6 +967,12 @@ fido_cred_id_len(const fido_cred_t *cred)
991 return (cred->attcred.id.len); 967 return (cred->attcred.id.len);
992} 968}
993 969
970int
971fido_cred_prot(const fido_cred_t *cred)
972{
973 return (cred->ext.prot);
974}
975
994const char * 976const char *
995fido_cred_fmt(const fido_cred_t *cred) 977fido_cred_fmt(const fido_cred_t *cred)
996{ 978{