diff options
Diffstat (limited to 'src/cbor.c')
-rw-r--r-- | src/cbor.c | 108 |
1 files changed, 82 insertions, 26 deletions
@@ -314,6 +314,35 @@ fail: | |||
314 | } | 314 | } |
315 | 315 | ||
316 | static int | 316 | static int |
317 | cbor_add_uint8(cbor_item_t *item, const char *key, uint8_t value) | ||
318 | { | ||
319 | struct cbor_pair pair; | ||
320 | int ok = -1; | ||
321 | |||
322 | memset(&pair, 0, sizeof(pair)); | ||
323 | |||
324 | if ((pair.key = cbor_build_string(key)) == NULL || | ||
325 | (pair.value = cbor_build_uint8(value)) == NULL) { | ||
326 | fido_log_debug("%s: cbor_build", __func__); | ||
327 | goto fail; | ||
328 | } | ||
329 | |||
330 | if (!cbor_map_add(item, pair)) { | ||
331 | fido_log_debug("%s: cbor_map_add", __func__); | ||
332 | goto fail; | ||
333 | } | ||
334 | |||
335 | ok = 0; | ||
336 | fail: | ||
337 | if (pair.key) | ||
338 | cbor_decref(&pair.key); | ||
339 | if (pair.value) | ||
340 | cbor_decref(&pair.value); | ||
341 | |||
342 | return (ok); | ||
343 | } | ||
344 | |||
345 | static int | ||
317 | cbor_add_arg(cbor_item_t *item, uint8_t n, cbor_item_t *arg) | 346 | cbor_add_arg(cbor_item_t *item, uint8_t n, cbor_item_t *arg) |
318 | { | 347 | { |
319 | struct cbor_pair pair; | 348 | struct cbor_pair pair; |
@@ -535,19 +564,29 @@ fail: | |||
535 | } | 564 | } |
536 | 565 | ||
537 | cbor_item_t * | 566 | cbor_item_t * |
538 | cbor_encode_extensions(int ext) | 567 | cbor_encode_extensions(const fido_cred_ext_t *ext) |
539 | { | 568 | { |
540 | cbor_item_t *item = NULL; | 569 | cbor_item_t *item = NULL; |
570 | size_t size = 0; | ||
541 | 571 | ||
542 | if (ext == 0 || ext != FIDO_EXT_HMAC_SECRET) | 572 | if (ext->mask & FIDO_EXT_HMAC_SECRET) |
543 | return (NULL); | 573 | size++; |
544 | 574 | if (ext->mask & FIDO_EXT_CRED_PROTECT) | |
545 | if ((item = cbor_new_definite_map(1)) == NULL) | 575 | size++; |
576 | if (size == 0 || (item = cbor_new_definite_map(size)) == NULL) | ||
546 | return (NULL); | 577 | return (NULL); |
547 | 578 | ||
548 | if (cbor_add_bool(item, "hmac-secret", FIDO_OPT_TRUE) < 0) { | 579 | if (ext->mask & FIDO_EXT_HMAC_SECRET) { |
549 | cbor_decref(&item); | 580 | if (cbor_add_bool(item, "hmac-secret", FIDO_OPT_TRUE) < 0) { |
550 | return (NULL); | 581 | cbor_decref(&item); |
582 | return (NULL); | ||
583 | } | ||
584 | } | ||
585 | if (ext->mask & FIDO_EXT_CRED_PROTECT) { | ||
586 | if (cbor_add_uint8(item, "credProtect", ext->prot) < 0) { | ||
587 | cbor_decref(&item); | ||
588 | return (NULL); | ||
589 | } | ||
551 | } | 590 | } |
552 | 591 | ||
553 | return (item); | 592 | return (item); |
@@ -1082,26 +1121,35 @@ fail: | |||
1082 | static int | 1121 | static int |
1083 | decode_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg) | 1122 | decode_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg) |
1084 | { | 1123 | { |
1085 | int *authdata_ext = arg; | 1124 | fido_cred_ext_t *authdata_ext = arg; |
1086 | char *type = NULL; | 1125 | char *type = NULL; |
1087 | int ok = -1; | 1126 | int ok = -1; |
1088 | 1127 | ||
1089 | if (cbor_string_copy(key, &type) < 0 || strcmp(type, "hmac-secret")) { | 1128 | if (cbor_string_copy(key, &type) < 0) { |
1090 | fido_log_debug("%s: cbor type", __func__); | 1129 | fido_log_debug("%s: cbor type", __func__); |
1091 | ok = 0; /* ignore */ | 1130 | ok = 0; /* ignore */ |
1092 | goto out; | 1131 | goto out; |
1093 | } | 1132 | } |
1094 | 1133 | ||
1095 | if (cbor_isa_float_ctrl(val) == false || | 1134 | if (strcmp(type, "hmac-secret") == 0) { |
1096 | cbor_float_get_width(val) != CBOR_FLOAT_0 || | 1135 | if (cbor_isa_float_ctrl(val) == false || |
1097 | cbor_is_bool(val) == false || *authdata_ext != 0) { | 1136 | cbor_float_get_width(val) != CBOR_FLOAT_0 || |
1098 | fido_log_debug("%s: cbor type", __func__); | 1137 | cbor_is_bool(val) == false) { |
1099 | goto out; | 1138 | fido_log_debug("%s: cbor type", __func__); |
1139 | goto out; | ||
1140 | } | ||
1141 | if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE) | ||
1142 | authdata_ext->mask |= FIDO_EXT_HMAC_SECRET; | ||
1143 | } else if (strcmp(type, "credProtect") == 0) { | ||
1144 | if (cbor_isa_uint(val) == false || | ||
1145 | cbor_int_get_width(val) != CBOR_INT_8) { | ||
1146 | fido_log_debug("%s: cbor type", __func__); | ||
1147 | goto out; | ||
1148 | } | ||
1149 | authdata_ext->mask |= FIDO_EXT_CRED_PROTECT; | ||
1150 | authdata_ext->prot = cbor_get_uint8(val); | ||
1100 | } | 1151 | } |
1101 | 1152 | ||
1102 | if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE) | ||
1103 | *authdata_ext |= FIDO_EXT_HMAC_SECRET; | ||
1104 | |||
1105 | ok = 0; | 1153 | ok = 0; |
1106 | out: | 1154 | out: |
1107 | free(type); | 1155 | free(type); |
@@ -1110,7 +1158,8 @@ out: | |||
1110 | } | 1158 | } |
1111 | 1159 | ||
1112 | static int | 1160 | static int |
1113 | decode_extensions(const unsigned char **buf, size_t *len, int *authdata_ext) | 1161 | decode_extensions(const unsigned char **buf, size_t *len, |
1162 | fido_cred_ext_t *authdata_ext) | ||
1114 | { | 1163 | { |
1115 | cbor_item_t *item = NULL; | 1164 | cbor_item_t *item = NULL; |
1116 | struct cbor_load_result cbor; | 1165 | struct cbor_load_result cbor; |
@@ -1118,8 +1167,9 @@ decode_extensions(const unsigned char **buf, size_t *len, int *authdata_ext) | |||
1118 | 1167 | ||
1119 | fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf, | 1168 | fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf, |
1120 | *len); | 1169 | *len); |
1170 | fido_log_xxd(*buf, *len); | ||
1121 | 1171 | ||
1122 | *authdata_ext = 0; | 1172 | memset(authdata_ext, 0, sizeof(*authdata_ext)); |
1123 | 1173 | ||
1124 | if ((item = cbor_load(*buf, *len, &cbor)) == NULL) { | 1174 | if ((item = cbor_load(*buf, *len, &cbor)) == NULL) { |
1125 | fido_log_debug("%s: cbor_load", __func__); | 1175 | fido_log_debug("%s: cbor_load", __func__); |
@@ -1129,7 +1179,6 @@ decode_extensions(const unsigned char **buf, size_t *len, int *authdata_ext) | |||
1129 | 1179 | ||
1130 | if (cbor_isa_map(item) == false || | 1180 | if (cbor_isa_map(item) == false || |
1131 | cbor_map_is_definite(item) == false || | 1181 | cbor_map_is_definite(item) == false || |
1132 | cbor_map_size(item) != 1 || | ||
1133 | cbor_map_iter(item, authdata_ext, decode_extension) < 0) { | 1182 | cbor_map_iter(item, authdata_ext, decode_extension) < 0) { |
1134 | fido_log_debug("%s: cbor type", __func__); | 1183 | fido_log_debug("%s: cbor type", __func__); |
1135 | goto fail; | 1184 | goto fail; |
@@ -1204,7 +1253,7 @@ fail: | |||
1204 | int | 1253 | int |
1205 | cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg, | 1254 | cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg, |
1206 | fido_blob_t *authdata_cbor, fido_authdata_t *authdata, | 1255 | fido_blob_t *authdata_cbor, fido_authdata_t *authdata, |
1207 | fido_attcred_t *attcred, int *authdata_ext) | 1256 | fido_attcred_t *attcred, fido_cred_ext_t *authdata_ext) |
1208 | { | 1257 | { |
1209 | const unsigned char *buf = NULL; | 1258 | const unsigned char *buf = NULL; |
1210 | size_t len; | 1259 | size_t len; |
@@ -1227,6 +1276,7 @@ cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg, | |||
1227 | len = cbor_bytestring_length(item); | 1276 | len = cbor_bytestring_length(item); |
1228 | 1277 | ||
1229 | fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len); | 1278 | fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len); |
1279 | fido_log_xxd(buf, len); | ||
1230 | 1280 | ||
1231 | if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) { | 1281 | if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) { |
1232 | fido_log_debug("%s: fido_buf_read", __func__); | 1282 | fido_log_debug("%s: fido_buf_read", __func__); |
@@ -1316,6 +1366,7 @@ decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg) | |||
1316 | { | 1366 | { |
1317 | fido_attstmt_t *attstmt = arg; | 1367 | fido_attstmt_t *attstmt = arg; |
1318 | char *name = NULL; | 1368 | char *name = NULL; |
1369 | int cose_alg = 0; | ||
1319 | int ok = -1; | 1370 | int ok = -1; |
1320 | 1371 | ||
1321 | if (cbor_string_copy(key, &name) < 0) { | 1372 | if (cbor_string_copy(key, &name) < 0) { |
@@ -1326,11 +1377,16 @@ decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg) | |||
1326 | 1377 | ||
1327 | if (!strcmp(name, "alg")) { | 1378 | if (!strcmp(name, "alg")) { |
1328 | if (cbor_isa_negint(val) == false || | 1379 | if (cbor_isa_negint(val) == false || |
1329 | cbor_int_get_width(val) != CBOR_INT_8 || | 1380 | cbor_get_int(val) > UINT16_MAX) { |
1330 | cbor_get_uint8(val) != -COSE_ES256 - 1) { | ||
1331 | fido_log_debug("%s: alg", __func__); | 1381 | fido_log_debug("%s: alg", __func__); |
1332 | goto out; | 1382 | goto out; |
1333 | } | 1383 | } |
1384 | if ((cose_alg = -(int)cbor_get_int(val) - 1) != COSE_ES256 && | ||
1385 | cose_alg != COSE_RS256 && cose_alg != COSE_EDDSA) { | ||
1386 | fido_log_debug("%s: unsupported cose_alg=%d", __func__, | ||
1387 | cose_alg); | ||
1388 | goto out; | ||
1389 | } | ||
1334 | } else if (!strcmp(name, "sig")) { | 1390 | } else if (!strcmp(name, "sig")) { |
1335 | if (cbor_bytestring_copy(val, &attstmt->sig.ptr, | 1391 | if (cbor_bytestring_copy(val, &attstmt->sig.ptr, |
1336 | &attstmt->sig.len) < 0) { | 1392 | &attstmt->sig.len) < 0) { |