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