@@ -40,6 +40,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
4040 CborByteString pinUvAuthParam = { 0 }, rpIdHash = { 0 };
4141 PublicKeyCredentialDescriptor credentialId = { 0 };
4242 PublicKeyCredentialUserEntity user = { 0 };
43+ CredentialRp rp_record = { 0 };
4344 size_t resp_size = 0 ;
4445 CborEncoder encoder , mapEncoder , mapEncoder2 ;
4546 uint8_t * raw_subpara = NULL ;
@@ -115,7 +116,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
115116 }
116117 CBOR_PARSE_MAP_END (map , 1 );
117118
118- if ((rpIdHash .present && rpIdHash .len != 32 ) || (credentialId .id .present && credentialId .id .len != CRED_RESIDENT_LEN )) {
119+ if ((rpIdHash .present && rpIdHash .len != RP_ID_HASH_LEN ) || (credentialId .id .present && credentialId .id .len != CRED_RESIDENT_LEN )) {
119120 CBOR_ERROR (CTAP1_ERR_INVALID_PARAMETER );
120121 }
121122
@@ -157,7 +158,6 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
157158 CBOR_CHECK (cbor_encode_uint (& mapEncoder , MAX_RESIDENT_CREDENTIALS - existing ));
158159 }
159160 else if (subcommand == 0x02 || subcommand == 0x03 ) {
160- file_t * rp_ef = NULL ;
161161 if (subcommand == 0x02 ) {
162162 if (verify ((uint8_t )pinUvAuthProtocol , ppaut .data , (const uint8_t * ) "\x02" , 1 , pinUvAuthParam .data ) == CborNoError ) {
163163 if (!(ppaut .permissions & CTAP_PERMISSION_PCMR )) {
@@ -172,57 +172,38 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
172172 CBOR_ERROR (CTAP2_ERR_PIN_AUTH_INVALID );
173173 }
174174 }
175- rp_counter = 1 ;
176- rp_total = 0 ;
175+ rp_counter = 0 ;
176+ if (credential_rp_count (& rp_total ) != PICOKEYS_OK ) {
177+ CBOR_ERROR (CTAP2_ERR_PROCESSING );
178+ }
177179 }
178180 else {
179- if (rp_counter > rp_total ) {
181+ if (rp_counter >= rp_total ) {
180182 CBOR_ERROR (CTAP2_ERR_NOT_ALLOWED );
181183 }
182184 }
183- uint16_t skip = 0 ;
184- for (int i = 0 ; i < MAX_RESIDENT_CREDENTIALS ; i ++ ) {
185- file_t * tef = file_search ((uint16_t )(EF_RP + i ));
186- if (file_has_data (tef ) && * file_get_data (tef ) > 0 ) {
187- if (++ skip == rp_counter ) {
188- if (rp_ef == NULL ) {
189- rp_ef = tef ;
190- }
191- if (subcommand == 0x03 ) {
192- break ;
193- }
194- }
195- if (subcommand == 0x02 ) {
196- rp_total ++ ;
197- }
198- }
199- }
200- if (rp_ef == NULL ) {
201- CBOR_ERROR (CTAP2_ERR_NO_CREDENTIALS );
185+ int rp_ret = credential_rp_load (rp_counter , & rp_record );
186+ if (rp_ret != PICOKEYS_OK ) {
187+ CBOR_ERROR (rp_ret == PICOKEYS_ERR_FILE_NOT_FOUND ? CTAP2_ERR_NO_CREDENTIALS : CTAP2_ERR_PROCESSING );
202188 }
203189 rp_counter ++ ;
204190 CBOR_CHECK (cbor_encoder_create_map (& encoder , & mapEncoder , subcommand == 0x02 ? 3 : 2 ));
205191 CBOR_CHECK (cbor_encode_uint (& mapEncoder , 0x03 ));
206192 CBOR_CHECK (cbor_encoder_create_map (& mapEncoder , & mapEncoder2 , 1 ));
207193 CBOR_CHECK (cbor_encode_text_stringz (& mapEncoder2 , "id" ));
208- uint8_t * rp_id = NULL ;
209- size_t rp_id_len = 0 ;
210- if (credential_rp_id_decrypt (rp_ef , & rp_id , & rp_id_len ) != 0 ) {
211- CBOR_ERROR (CTAP2_ERR_PROCESSING );
212- }
213- error = cbor_encode_text_string (& mapEncoder2 , (char * ) rp_id , rp_id_len );
214- free (rp_id );
194+ error = cbor_encode_text_string (& mapEncoder2 , (char * ) rp_record .id , rp_record .id_len );
215195 if (error != CborNoError ) {
216- printf ("Cannot encode CBOR [%s:%d]: cbor_encode_text_string(&mapEncoder2, (char *) rp_id, rp_id_len ) (%d)\n" , __FILE__ , __LINE__ , error );
196+ printf ("Cannot encode CBOR [%s:%d]: cbor_encode_text_string(&mapEncoder2, (char *) rp_record.id, rp_record.id_len ) (%d)\n" , __FILE__ , __LINE__ , error );
217197 goto err ;
218198 }
219199 CBOR_CHECK (cbor_encoder_close_container (& mapEncoder , & mapEncoder2 ));
220200 CBOR_CHECK (cbor_encode_uint (& mapEncoder , 0x04 ));
221- CBOR_CHECK (cbor_encode_byte_string (& mapEncoder , file_get_data ( rp_ef ) + 1 , 32 ));
201+ CBOR_CHECK (cbor_encode_byte_string (& mapEncoder , rp_record . id_hash , sizeof ( rp_record . id_hash ) ));
222202 if (subcommand == 0x02 ) {
223203 CBOR_CHECK (cbor_encode_uint (& mapEncoder , 0x05 ));
224204 CBOR_CHECK (cbor_encode_uint (& mapEncoder , rp_total ));
225205 }
206+ credential_rp_free (& rp_record );
226207 }
227208 else if (subcommand == 0x04 || subcommand == 0x05 ) {
228209 if (subcommand == 0x04 && rpIdHash .present == false) {
@@ -241,7 +222,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
241222 }
242223 if (is_preview == false &&
243224 (!(paut .permissions & CTAP_PERMISSION_CM ) ||
244- (paut .has_rp_id == true && memcmp (paut .rp_id_hash , rpIdHash .data , 32 ) != 0 ))) {
225+ (paut .has_rp_id == true && memcmp (paut .rp_id_hash , rpIdHash .data , RP_ID_HASH_LEN ) != 0 ))) {
245226 CBOR_ERROR (CTAP2_ERR_PIN_AUTH_INVALID );
246227 }
247228 }
@@ -406,30 +387,21 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
406387 if (verify ((uint8_t )pinUvAuthProtocol , paut .data , raw_subpara - 1 , (uint16_t )(raw_subpara_len + 1 ), pinUvAuthParam .data ) != CborNoError ) {
407388 CBOR_ERROR (CTAP2_ERR_PIN_AUTH_INVALID );
408389 }
409- if (is_preview == false && (!(paut .permissions & CTAP_PERMISSION_CM ) || (paut .has_rp_id == true && memcmp (paut .rp_id_hash , rpIdHash .data , 32 ) != 0 ))) {
390+ if (is_preview == false && (!(paut .permissions & CTAP_PERMISSION_CM ) || (paut .has_rp_id == true && memcmp (paut .rp_id_hash , rpIdHash .data , RP_ID_HASH_LEN ) != 0 ))) {
410391 CBOR_ERROR (CTAP2_ERR_PIN_AUTH_INVALID );
411392 }
412393 for (int i = 0 ; i < MAX_RESIDENT_CREDENTIALS ; i ++ ) {
413394 file_t * ef = file_search ((uint16_t )(EF_CRED + i ));
414395 if (file_has_data (ef ) && credential_resident_matches_id (ef , credentialId .id .data , credentialId .id .len )) {
415- uint8_t rp_id_hash [32 ];
396+ bool legacy_rp = !resident_container_is_marker (ef );
397+ uint8_t rp_id_hash [RP_ID_HASH_LEN ];
416398 if (credential_resident_rp_id_hash (ef , rp_id_hash ) != PICOKEYS_OK || credential_resident_delete (ef ) != PICOKEYS_OK ) {
417399 CBOR_ERROR (CTAP2_ERR_NOT_ALLOWED );
418400 }
419- for (int j = 0 ; j < MAX_RESIDENT_CREDENTIALS ; j ++ ) {
420- file_t * rp_ef = file_search ((uint16_t )(EF_RP + j ));
421- if (file_has_data (rp_ef ) && memcmp (file_get_data (rp_ef ) + 1 , rp_id_hash , 32 ) == 0 ) {
422- uint8_t * rp_data = (uint8_t * ) calloc (1 , file_get_size (rp_ef ));
423- memcpy (rp_data , file_get_data (rp_ef ), file_get_size (rp_ef ));
424- rp_data [0 ] -= 1 ;
425- if (rp_data [0 ] == 0 ) {
426- file_delete (rp_ef );
427- }
428- else {
429- file_put_data (rp_ef , rp_data , file_get_size (rp_ef ));
430- }
431- free (rp_data );
432- break ;
401+ if (legacy_rp ) {
402+ int rp_ret = credential_rp_legacy_decrement (rp_id_hash );
403+ if (rp_ret != PICOKEYS_OK && rp_ret != PICOKEYS_ERR_FILE_NOT_FOUND ) {
404+ CBOR_ERROR (CTAP2_ERR_NOT_ALLOWED );
433405 }
434406 }
435407 dev_state_update (DEV_STATE_CRED_STATE );
@@ -447,14 +419,14 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
447419 if (verify ((uint8_t )pinUvAuthProtocol , paut .data , raw_subpara - 1 , (uint16_t )(raw_subpara_len + 1 ), pinUvAuthParam .data ) != CborNoError ) {
448420 CBOR_ERROR (CTAP2_ERR_PIN_AUTH_INVALID );
449421 }
450- if (is_preview == false && (!(paut .permissions & CTAP_PERMISSION_CM ) || (paut .has_rp_id == true && memcmp (paut .rp_id_hash , rpIdHash .data , 32 ) != 0 ))) {
422+ if (is_preview == false && (!(paut .permissions & CTAP_PERMISSION_CM ) || (paut .has_rp_id == true && memcmp (paut .rp_id_hash , rpIdHash .data , RP_ID_HASH_LEN ) != 0 ))) {
451423 CBOR_ERROR (CTAP2_ERR_PIN_AUTH_INVALID );
452424 }
453425 for (int i = 0 ; i < MAX_RESIDENT_CREDENTIALS ; i ++ ) {
454426 file_t * ef = file_search ((uint16_t )(EF_CRED + i ));
455427 if (file_has_data (ef ) && credential_resident_matches_id (ef , credentialId .id .data , credentialId .id .len )) {
456428 Credential cred = { 0 };
457- uint8_t rp_id_hash [32 ];
429+ uint8_t rp_id_hash [RP_ID_HASH_LEN ];
458430 if (credential_resident_rp_id_hash (ef , rp_id_hash ) != PICOKEYS_OK || credential_load_resident (ef , rp_id_hash , & cred ) != 0 ) {
459431 CBOR_ERROR (CTAP2_ERR_NOT_ALLOWED );
460432 }
@@ -485,6 +457,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
485457 CBOR_CHECK (cbor_encoder_close_container (& encoder , & mapEncoder ));
486458 resp_size = cbor_encoder_get_buffer_size (& encoder , ctap_resp -> init .data + 1 );
487459err :
460+ credential_rp_free (& rp_record );
488461 CBOR_FREE_BYTE_STRING (pinUvAuthParam );
489462
490463 if (asserted == false) {
0 commit comments