Vulnerability: A heap use after free issue was found in Opensc before version 0.22.0 in sc_file_valid.
Vulnerability ID: CVE-2021-42779
CWE: CWE-416
Severity score: 2.9
Project: https://github.com/OpenSC/OpenSC
Published: 2022-04-18
File: src/libopensc/pkcs15-oberthur.c
Commit message: oberthur: Correctly check for return values

Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28843
Commit author: Jakub Jelen

Vulnerable version (before fix):
 sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, 	if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)   { 		struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL; 		const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ); 		int ii;  		if (acl == NULL) { 			sc_file_free(file); sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, 			LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); 		}  		rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10); 		if (rv != SC_SUCCESS) { 			sc_file_free(file); 			free(*out); 			*out = NULL; 			LOG_TEST_RET(ctx, rv, "Cannot read oberthur file: get AUTH objects error"); 		}  		for (ii=0; ii<rv; ii++)   { 			struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data; 			sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i", 					auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method); 			if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method)   { 				pin_obj = objs[ii]; 				break;

Fixed version (after fix):
 sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, 	if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)   { 		struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL; 		const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ); 		int ii, nobjs;  		if (acl == NULL) { 			sc_file_free(file); sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, 			LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); 		}  		nobjs = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10); 		if (nobjs < 1) { 			sc_file_free(file); 			free(*out); 			*out = NULL; 			LOG_TEST_RET(ctx, SC_ERROR_DATA_OBJECT_NOT_FOUND, 				"Cannot read oberthur file: get AUTH objects error"); 		}  		for (ii = 0; ii < nobjs; ii++) { 			struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data; 			sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i", 				auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method); 			if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method)   { 				pin_obj = objs[ii]; 				break;

Patch:
patch: @@ -304,7 +304,7 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
 	if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)   {
 		struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL;
 		const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ);
-		int ii;
+		int ii, nobjs;
 
 		if (acl == NULL) {
 			sc_file_free(file);
@@ -313,18 +313,19 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
 			LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
 		}
 
-		rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
-		if (rv != SC_SUCCESS) {
+		nobjs = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
+		if (nobjs < 1) {
 			sc_file_free(file);
 			free(*out);
 			*out = NULL;
-			LOG_TEST_RET(ctx, rv, "Cannot read oberthur file: get AUTH objects error");
+			LOG_TEST_RET(ctx, SC_ERROR_DATA_OBJECT_NOT_FOUND,
+				"Cannot read oberthur file: get AUTH objects error");
 		}
 
-		for (ii=0; ii<rv; ii++)   {
+		for (ii = 0; ii < nobjs; ii++) {
 			struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data;
 			sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i",
-					auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
+				auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
 			if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method)   {
 				pin_obj = objs[ii];
 				break;
path: src/libopensc/pkcs15-oberthur.c