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