diff options
Diffstat (limited to 'src/cred.c')
-rw-r--r-- | src/cred.c | 122 |
1 files changed, 52 insertions, 70 deletions
@@ -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: | |||
126 | static int | 126 | static int |
127 | fido_dev_make_cred_rx(fido_dev_t *dev, fido_cred_t *cred, int ms) | 127 | fido_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 | |||
170 | fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin) | 170 | fido_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 | ||
181 | static int | 182 | static int |
182 | check_extensions(int authdata_ext, int ext) | 183 | check_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 | ||
193 | int | 188 | int |
@@ -208,48 +203,6 @@ fido_check_rp_id(const char *id, const unsigned char *obtained_hash) | |||
208 | } | 203 | } |
209 | 204 | ||
210 | static int | 205 | static int |
211 | get_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; | ||
245 | fail: | ||
246 | if (item != NULL) | ||
247 | cbor_decref(&item); | ||
248 | |||
249 | return (ok); | ||
250 | } | ||
251 | |||
252 | static int | ||
253 | get_signed_hash_u2f(fido_blob_t *dgst, const unsigned char *rp_id, | 206 | get_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: | |||
395 | int | 348 | int |
396 | fido_cred_verify_self(const fido_cred_t *cred) | 349 | fido_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: | |||
810 | int | 763 | int |
811 | fido_cred_set_extensions(fido_cred_t *cred, int ext) | 764 | fido_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 | ||
846 | int | 803 | int |
804 | fido_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 | |||
822 | int | ||
847 | fido_cred_set_fmt(fido_cred_t *cred, const char *fmt) | 823 | fido_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 | ||
970 | int | ||
971 | fido_cred_prot(const fido_cred_t *cred) | ||
972 | { | ||
973 | return (cred->ext.prot); | ||
974 | } | ||
975 | |||
994 | const char * | 976 | const char * |
995 | fido_cred_fmt(const fido_cred_t *cred) | 977 | fido_cred_fmt(const fido_cred_t *cred) |
996 | { | 978 | { |