1 /*
2  * Copyright (C) 2020 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 #include <regex.h>
18 
19 #include <android-base/properties.h>
20 #include <hardware/hw_auth_token.h>
21 
22 namespace aidl::android::hardware::security::keymint {
23 
24 namespace {
25 
26 constexpr char kPlatformVersionProp[] = "ro.build.version.release";
27 constexpr char kPlatformVersionRegex[] = "^([0-9]{1,2})(\\.([0-9]{1,2}))?(\\.([0-9]{1,2}))?";
28 constexpr size_t kMajorVersionMatch = 1;
29 constexpr size_t kMinorVersionMatch = 3;
30 constexpr size_t kSubminorVersionMatch = 5;
31 constexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1;
32 
33 constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
34 constexpr char kVendorPatchlevelProp[] = "ro.vendor.build.security_patch";
35 constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-([0-9]{2})$";
36 constexpr size_t kYearMatch = 1;
37 constexpr size_t kMonthMatch = 2;
38 constexpr size_t kDayMatch = 3;
39 constexpr size_t kPatchlevelMatchCount = kDayMatch + 1;
40 
match_to_uint32(const char * expression,const regmatch_t & match)41 uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
42     if (match.rm_so == -1) return 0;
43 
44     size_t len = match.rm_eo - match.rm_so;
45     std::string s(expression + match.rm_so, len);
46     return std::stoul(s);
47 }
48 
wait_and_get_property(const char * prop)49 std::string wait_and_get_property(const char* prop) {
50     std::string prop_value;
51     while (!::android::base::WaitForPropertyCreation(prop))
52         ;
53     prop_value = ::android::base::GetProperty(prop, "" /* default */);
54     return prop_value;
55 }
56 
getOsVersion(const char * version_str)57 uint32_t getOsVersion(const char* version_str) {
58     regex_t regex;
59     if (regcomp(&regex, kPlatformVersionRegex, REG_EXTENDED)) {
60         return 0;
61     }
62 
63     regmatch_t matches[kPlatformVersionMatchCount];
64     int not_match =
65             regexec(&regex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
66     regfree(&regex);
67     if (not_match) {
68         return 0;
69     }
70 
71     uint32_t major = match_to_uint32(version_str, matches[kMajorVersionMatch]);
72     uint32_t minor = match_to_uint32(version_str, matches[kMinorVersionMatch]);
73     uint32_t subminor = match_to_uint32(version_str, matches[kSubminorVersionMatch]);
74 
75     return (major * 100 + minor) * 100 + subminor;
76 }
77 
78 enum class PatchlevelOutput { kYearMonthDay, kYearMonth };
79 
getPatchlevel(const char * patchlevel_str,PatchlevelOutput detail)80 uint32_t getPatchlevel(const char* patchlevel_str, PatchlevelOutput detail) {
81     regex_t regex;
82     if (regcomp(&regex, kPatchlevelRegex, REG_EXTENDED) != 0) {
83         return 0;
84     }
85 
86     regmatch_t matches[kPatchlevelMatchCount];
87     int not_match = regexec(&regex, patchlevel_str, kPatchlevelMatchCount, matches, 0 /* flags */);
88     regfree(&regex);
89     if (not_match) {
90         return 0;
91     }
92 
93     uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
94     uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
95 
96     if (month < 1 || month > 12) {
97         return 0;
98     }
99 
100     switch (detail) {
101         case PatchlevelOutput::kYearMonthDay: {
102             uint32_t day = match_to_uint32(patchlevel_str, matches[kDayMatch]);
103             if (day < 1 || day > 31) {
104                 return 0;
105             }
106             return year * 10000 + month * 100 + day;
107         }
108         case PatchlevelOutput::kYearMonth:
109             return year * 100 + month;
110     }
111 }
112 
113 }  // anonymous namespace
114 
getOsVersion()115 uint32_t getOsVersion() {
116     std::string version = wait_and_get_property(kPlatformVersionProp);
117     return getOsVersion(version.c_str());
118 }
119 
getOsPatchlevel()120 uint32_t getOsPatchlevel() {
121     std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
122     return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonth);
123 }
124 
getVendorPatchlevel()125 uint32_t getVendorPatchlevel() {
126     std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp);
127     return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonthDay);
128 }
129 
130 }  // namespace aidl::android::hardware::security::keymint
131