1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define TLOG_TAG "apploader-app-manifest"
18
19 #include "app_manifest_parser.h"
20 #include <lib/app_manifest/app_manifest.h>
21 #include <trusty_log.h>
22 #include <uapi/err.h>
23
apploader_parse_manifest_from_metadata(struct apploader_package_metadata * pkg_meta,struct manifest_extracts * manifest_extracts)24 extern "C" bool apploader_parse_manifest_from_metadata(
25 struct apploader_package_metadata* pkg_meta,
26 struct manifest_extracts* manifest_extracts) {
27 return apploader_parse_manifest((const char*)pkg_meta->manifest_start,
28 pkg_meta->manifest_size, manifest_extracts);
29 }
30
apploader_parse_manifest(const char * manifest_start,const size_t manifest_size,struct manifest_extracts * manifest_extracts)31 extern "C" bool apploader_parse_manifest(
32 const char* manifest_start,
33 const size_t manifest_size,
34 struct manifest_extracts* manifest_extracts) {
35 struct app_manifest_iterator iter;
36 app_manifest_iterator_reset(&iter, manifest_start, manifest_size);
37
38 struct manifest_extracts out_ext = {
39 /* Applications are critical by default */
40 .non_critical_app = false,
41 /* Apps without a version in the manifest get a default of 0 */
42 .version = 0,
43 /* Applications do not require encryption by default */
44 .requires_encryption = false,
45 };
46
47 struct app_manifest_config_entry entry;
48 int out_error;
49 bool uuid_found = false;
50 bool version_found = false;
51 bool min_version_found = false;
52 bool mgmt_flags_found = false;
53 bool apploader_flags_found = false;
54
55 while (app_manifest_iterator_next(&iter, &entry, &out_error)) {
56 if (out_error != NO_ERROR) {
57 TLOGE("Error iterating over manifest entries (%d)\n", out_error);
58 return false;
59 }
60 switch (entry.key) {
61 case APP_MANIFEST_CONFIG_KEY_UUID:
62 if (uuid_found) {
63 TLOGE("Manifest contained duplicate UUID entry");
64 return false;
65 }
66 out_ext.uuid = entry.value.uuid;
67 uuid_found = true;
68 break;
69 case APP_MANIFEST_CONFIG_KEY_MGMT_FLAGS:
70 if (mgmt_flags_found) {
71 TLOGE("Manifest contained duplicate mgmt_flags entry");
72 return false;
73 }
74 if (entry.value.mgmt_flags &
75 APP_MANIFEST_MGMT_FLAGS_NON_CRITICAL_APP) {
76 out_ext.non_critical_app = true;
77 }
78 mgmt_flags_found = true;
79 break;
80 case APP_MANIFEST_CONFIG_KEY_VERSION:
81 if (version_found) {
82 TLOGE("Manifest contained duplicate version entry");
83 return false;
84 }
85 out_ext.version = entry.value.version;
86 version_found = true;
87 break;
88 case APP_MANIFEST_CONFIG_KEY_MIN_VERSION:
89 if (min_version_found) {
90 TLOGE("Manifest contained duplicate min_version entry");
91 return false;
92 }
93 out_ext.min_version = entry.value.min_version;
94 min_version_found = true;
95 break;
96 case APP_MANIFEST_CONFIG_KEY_APPLOADER_FLAGS:
97 if (apploader_flags_found) {
98 TLOGE("Manifest contained duplicate apploader_flags entry");
99 return false;
100 }
101 if (entry.value.apploader_flags &
102 APP_MANIFEST_APPLOADER_FLAGS_REQUIRES_ENCRYPTION) {
103 out_ext.requires_encryption = true;
104 }
105 apploader_flags_found = true;
106 break;
107 case APP_MANIFEST_CONFIG_KEY_APP_NAME:
108 case APP_MANIFEST_CONFIG_KEY_MIN_STACK_SIZE:
109 case APP_MANIFEST_CONFIG_KEY_MIN_HEAP_SIZE:
110 case APP_MANIFEST_CONFIG_KEY_MAP_MEM:
111 case APP_MANIFEST_CONFIG_KEY_START_PORT:
112 case APP_MANIFEST_CONFIG_KEY_PINNED_CPU:
113 case APP_MANIFEST_CONFIG_KEY_PRIORITY:
114 case APP_MANIFEST_CONFIG_KEY_MIN_SHADOW_STACK_SIZE:
115 /* The apploader has no use for these values */
116 break;
117 }
118 }
119
120 /* min_version defaults to the app version if not specified */
121 if (!min_version_found) {
122 out_ext.min_version = out_ext.version;
123 }
124
125 if (out_ext.version < out_ext.min_version) {
126 TLOGE("Manifest contained invalid min_version entry");
127 return false;
128 }
129
130 if (uuid_found) {
131 *manifest_extracts = out_ext;
132 }
133
134 return (uuid_found);
135 }
136