@@ -438,10 +438,7 @@ int credential_create(CborCharString *rpId, CborByteString *userId, CborCharStri
438438 mbedtls_chachapoly_context chatx ;
439439 mbedtls_chachapoly_init (& chatx );
440440 mbedtls_chachapoly_setkey (& chatx , key );
441- int ret = mbedtls_chachapoly_encrypt_and_tag (& chatx , rs , iv , rp_id_hash , RP_ID_HASH_LEN ,
442- cred_id + CRED_PROTO_LEN + CRED_IV_LEN ,
443- cred_id + CRED_PROTO_LEN + CRED_IV_LEN ,
444- cred_id + CRED_PROTO_LEN + CRED_IV_LEN + rs );
441+ int ret = mbedtls_chachapoly_encrypt_and_tag (& chatx , rs , iv , rp_id_hash , RP_ID_HASH_LEN , cred_id + CRED_PROTO_LEN + CRED_IV_LEN , cred_id + CRED_PROTO_LEN + CRED_IV_LEN , cred_id + CRED_PROTO_LEN + CRED_IV_LEN + rs );
445442 mbedtls_chachapoly_free (& chatx );
446443 if (ret != 0 ) {
447444 CBOR_ERROR (CTAP1_ERR_OTHER );
@@ -639,7 +636,7 @@ static int credential_parse_metadata(const uint8_t *data, size_t data_len, Crede
639636 CBOR_PARSE_MAP_END (_f1 , 2 );
640637 }
641638 else if (val_u == 0x0C ) { CBOR_FIELD_GET_UINT (cred -> rtc_creation , 1 ); }
642- else if (val_u == 0x0D ) { CBOR_ADVANCE ( 1 ); }
639+ else if (val_u == 0x0D ) { CBOR_FIELD_GET_BYTES ( cred -> residentId , 1 ); }
643640 else { CBOR_ADVANCE (1 ); }
644641 }
645642 CBOR_PARSE_MAP_END (map , 1 );
@@ -784,10 +781,16 @@ int credential_import(const credential_import_record_t *record) {
784781 }
785782 Credential parsed = {0 };
786783 int ret = credential_parse_metadata (record -> metadata , record -> metadata_len , & parsed );
784+ const uint8_t * resident_id = parsed .residentId .data ;
785+ size_t resident_id_len = parsed .residentId .len ;
786+ if (!parsed .residentId .present && credential_is_resident (record -> requested_id , record -> requested_id_len )) {
787+ resident_id = record -> requested_id ;
788+ resident_id_len = record -> requested_id_len ;
789+ }
787790 mbedtls_ecp_group_id curve = fido_curve_to_mbedtls ((int )parsed .curve );
788791 uint8_t rp_id_hash [RP_ID_HASH_LEN ] = {0 };
789792 uint8_t credential_hash [RP_ID_HASH_LEN ] = {0 };
790- if (ret != PICOKEYS_OK || !parsed .rpId .present || !parsed .rpIdHash .present || parsed .rpIdHash .len != RP_ID_HASH_LEN || parsed .rpId .len != record -> rp_id_len || mbedtls_ct_memcmp (parsed .rpId .data , record -> rp_id , record -> rp_id_len ) != 0 || !credential_algorithm_matches_curve (parsed .alg , parsed .curve ) || curve == MBEDTLS_ECP_DP_NONE ) {
793+ if (ret != PICOKEYS_OK || !parsed .rpId .present || !parsed .rpIdHash .present || parsed .rpIdHash .len != RP_ID_HASH_LEN || parsed .rpId .len != record -> rp_id_len || mbedtls_ct_memcmp (parsed .rpId .data , record -> rp_id , record -> rp_id_len ) != 0 || !credential_algorithm_matches_curve (parsed .alg , parsed .curve ) || curve == MBEDTLS_ECP_DP_NONE || ! resident_id || resident_id_len != CRED_RESIDENT_LEN || ! credential_is_resident ( resident_id , resident_id_len ) ) {
791794 log_errstr ("credential import: metadata validation failed parse_ret=%d rp_id=\"%.*s\" rp_id_present=%d rp_id_len=%zu expected_len=%zu algorithm=%d curve=%d" , ret , parsed .rpId .present ? (int )(parsed .rpId .len > 32u ? 32u : parsed .rpId .len ) : 0 , parsed .rpId .present ? parsed .rpId .data : "" , parsed .rpId .present , parsed .rpId .len , record -> rp_id_len , parsed .alg , parsed .curve );
792795 credential_free (& parsed );
793796 return PICOKEYS_WRONG_DATA ;
@@ -818,10 +821,7 @@ int credential_import(const credential_import_record_t *record) {
818821 }
819822 uint8_t client_id [CRED_RESIDENT_LEN ] = {0 };
820823 if (ret == 0 && error == CborNoError ) {
821- ret = credential_derive_resident (record -> credential_id , record -> credential_id_len , client_id );
822- if (ret != PICOKEYS_OK ) {
823- log_errstr ("credential import: resident ID derivation failed ret=%d credential_id_len=%zu" , ret , record -> credential_id_len );
824- }
824+ memcpy (client_id , resident_id , sizeof (client_id ));
825825 }
826826 int slot = -1 ;
827827 if (ret == 0 ) {
@@ -1096,17 +1096,25 @@ int credential_load_resident(const file_t *ef, const uint8_t *rp_id_hash, Creden
10961096 if (ret == PICOKEYS_OK && (resident_metadata .properties & FIDO_RESIDENT_PROPERTY_IMPORTED ) != 0 ) {
10971097 cred -> imported = true;
10981098 ret = credential_resident_container_read_alloc (ef , FIDO_RESIDENT_OBJECT_METADATA , & metadata , & metadata_len );
1099- if (ret == PICOKEYS_OK ) ret = credential_resident_container_read_alloc (ef , FIDO_RESIDENT_OBJECT_PRIVATE_KEY , & private_key , & private_key_len );
1100- if (ret == PICOKEYS_OK ) ret = credential_parse_metadata (metadata , metadata_len , cred );
1099+ if (ret == PICOKEYS_OK ) {
1100+ ret = credential_resident_container_read_alloc (ef , FIDO_RESIDENT_OBJECT_PRIVATE_KEY , & private_key , & private_key_len );
1101+ }
1102+ if (ret == PICOKEYS_OK ) {
1103+ ret = credential_parse_metadata (metadata , metadata_len , cred );
1104+ }
11011105 if (ret == PICOKEYS_OK ) {
11021106 cred -> id .data = (uint8_t * )calloc (1 , credential_len );
1103- if (!cred -> id .data ) ret = PICOKEYS_ERR_NO_MEMORY ;
1107+ if (!cred -> id .data ) {
1108+ ret = PICOKEYS_ERR_NO_MEMORY ;
1109+ }
11041110 else {
11051111 memcpy (cred -> id .data , credential , credential_len );
11061112 cred -> id .len = credential_len ;
11071113 cred -> id .present = true;
11081114 cred -> privateKey .data = (uint8_t * )calloc (1 , private_key_len );
1109- if (!cred -> privateKey .data ) ret = PICOKEYS_ERR_NO_MEMORY ;
1115+ if (!cred -> privateKey .data ) {
1116+ ret = PICOKEYS_ERR_NO_MEMORY ;
1117+ }
11101118 else {
11111119 memcpy (cred -> privateKey .data , private_key , private_key_len );
11121120 cred -> privateKey .len = private_key_len ;
0 commit comments