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 #include "keymint_utils.h"
17
18 #include <regex.h>
19
20 #include <android-base/properties.h>
21 #include <android-base/parseint.h>
22 namespace keymint::javacard {
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 uint32_t val = 0;
47 android::base::ParseUint(s, &val);
48 return val;
49 }
50
wait_and_get_property(const char * prop)51 std::string wait_and_get_property(const char* prop) {
52 std::string prop_value;
53 while (!::android::base::WaitForPropertyCreation(prop));
54
55 prop_value = ::android::base::GetProperty(prop, "" /* default */);
56 return prop_value;
57 }
58
getOsVersion(const char * version_str)59 uint32_t getOsVersion(const char* version_str) {
60 regex_t regex;
61 if (regcomp(®ex, kPlatformVersionRegex, REG_EXTENDED)) {
62 return 0;
63 }
64
65 regmatch_t matches[kPlatformVersionMatchCount];
66 int not_match =
67 regexec(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
68 regfree(®ex);
69 if (not_match) {
70 return 0;
71 }
72
73 uint32_t major = match_to_uint32(version_str, matches[kMajorVersionMatch]);
74 uint32_t minor = match_to_uint32(version_str, matches[kMinorVersionMatch]);
75 uint32_t subminor = match_to_uint32(version_str, matches[kSubminorVersionMatch]);
76
77 return (major * 100 + minor) * 100 + subminor;
78 }
79
80 enum class PatchlevelOutput { kYearMonthDay, kYearMonth };
81
getPatchlevel(const char * patchlevel_str,PatchlevelOutput detail)82 uint32_t getPatchlevel(const char* patchlevel_str, PatchlevelOutput detail) {
83 regex_t regex;
84 if (regcomp(®ex, kPatchlevelRegex, REG_EXTENDED) != 0) {
85 return 0;
86 }
87
88 regmatch_t matches[kPatchlevelMatchCount];
89 int not_match = regexec(®ex, patchlevel_str, kPatchlevelMatchCount, matches, 0 /* flags */);
90 regfree(®ex);
91 if (not_match) {
92 return 0;
93 }
94
95 uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
96 uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
97
98 if (month < 1 || month > 12) {
99 return 0;
100 }
101
102 switch (detail) {
103 case PatchlevelOutput::kYearMonthDay: {
104 uint32_t day = match_to_uint32(patchlevel_str, matches[kDayMatch]);
105 if (day < 1 || day > 31) {
106 return 0;
107 }
108 return year * 10000 + month * 100 + day;
109 }
110 case PatchlevelOutput::kYearMonth:
111 return year * 100 + month;
112 }
113 }
114
115 } // anonymous namespace
116
getOsVersion()117 uint32_t getOsVersion() {
118 std::string version = wait_and_get_property(kPlatformVersionProp);
119 return getOsVersion(version.c_str());
120 }
121
getOsPatchlevel()122 uint32_t getOsPatchlevel() {
123 std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
124 return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonth);
125 }
126
getVendorPatchlevel()127 uint32_t getVendorPatchlevel() {
128 std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp);
129 return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonthDay);
130 }
131
132 } // namespace keymint::javacard
133