1cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden/*
2cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * Copyright (C) 2016 The Android Open Source Project
3cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden *
4cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * Licensed under the Apache License, Version 2.0 (the "License");
5cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * you may not use this file except in compliance with the License.
6cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * You may obtain a copy of the License at
7cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden *
8cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden *      http://www.apache.org/licenses/LICENSE-2.0
9cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden *
10cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * Unless required by applicable law or agreed to in writing, software
11cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * distributed under the License is distributed on an "AS IS" BASIS,
12cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * See the License for the specific language governing permissions and
14cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden * limitations under the License.
15cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden */
16cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
17cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#include <keymaster/keymaster_configuration.h>
18cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
19cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#include <regex>
20cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#include <string>
21cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
22cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#include <regex.h>
23cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
24cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#define LOG_TAG "keymaster"
25cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#include <cutils/log.h>
26cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
27cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#ifndef KEYMASTER_UNIT_TEST_BUILD
28cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#include <cutils/properties.h>
29cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#else
30cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#define PROPERTY_VALUE_MAX 80 /* Value doesn't matter */
31cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenvoid property_get(const char* /* prop_name */, char* /* prop */, const char* /* default */) {}
32cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#endif
33cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
34cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden#include <keymaster/authorization_set.h>
35cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
36cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdennamespace keymaster {
37cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
38cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdennamespace {
39cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
40cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr char kPlatformVersionProp[] = "ro.build.version.release";
41cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr char kPlatformVersionRegex[] = "^([0-9]{1,2})(\\.([0-9]{1,2}))?(\\.([0-9]{1,2}))?";
42cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr size_t kMajorVersionMatch = 1;
43cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr size_t kMinorVersionMatch = 3;
44cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr size_t kSubminorVersionMatch = 5;
45cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1;
46cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
47cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
48cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr char kPlatformPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
49cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr size_t kYearMatch = 1;
50cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr size_t kMonthMatch = 2;
51cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenconstexpr size_t kPlatformPatchlevelMatchCount = kMonthMatch + 1;
52cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
53cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenuint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
54cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    if (match.rm_so == -1)
55cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        return 0;
56cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
57cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    size_t len = match.rm_eo - match.rm_so;
58cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    std::string s(expression + match.rm_so, len);
59cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    return std::stoul(s);
60cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden}
61cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
62cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden}  // anonymous namespace
63cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
64cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenkeymaster_error_t ConfigureDevice(keymaster2_device_t* dev, uint32_t os_version,
65cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden                                  uint32_t os_patchlevel) {
66cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    AuthorizationSet config_params(AuthorizationSetBuilder()
67cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden                                       .Authorization(keymaster::TAG_OS_VERSION, os_version)
68cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden                                       .Authorization(keymaster::TAG_OS_PATCHLEVEL, os_patchlevel));
69cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    return dev->configure(dev, &config_params);
70cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden}
71cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
72cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenkeymaster_error_t ConfigureDevice(keymaster2_device_t* dev) {
7323fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    return ConfigureDevice(dev, GetOsVersion(), GetOsPatchlevel());
74cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden}
75cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
76cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenuint32_t GetOsVersion(const char* version_str) {
77cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    regex_t regex;
78cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    if (regcomp(&regex, kPlatformVersionRegex, REG_EXTENDED)) {
79cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        ALOGE("Failed to compile version regex! (%s)", kPlatformVersionRegex);
80cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        return 0;
81cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    }
82cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
83cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    regmatch_t matches[kPlatformVersionMatchCount];
8423fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    int not_match =
8523fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden        regexec(&regex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
8638837e9dbf0be3f0f6014e66c6d92a75205b964eThurston Hou Yeen Dang    regfree(&regex);
8738837e9dbf0be3f0f6014e66c6d92a75205b964eThurston Hou Yeen Dang    if (not_match) {
88cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        ALOGI("Platform version string does not match expected format.  Using version 0.");
89cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        return 0;
90cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    }
91cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
92cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    uint32_t major = match_to_uint32(version_str, matches[kMajorVersionMatch]);
93cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    uint32_t minor = match_to_uint32(version_str, matches[kMinorVersionMatch]);
94cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    uint32_t subminor = match_to_uint32(version_str, matches[kSubminorVersionMatch]);
95cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
96cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    return (major * 100 + minor) * 100 + subminor;
97cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden}
98cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
9923fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willdenuint32_t GetOsVersion() {
10023fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    char version_str[PROPERTY_VALUE_MAX];
10123fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    property_get(kPlatformVersionProp, version_str, "" /* default */);
10223fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    return GetOsVersion(version_str);
10323fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden}
10423fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden
105cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willdenuint32_t GetOsPatchlevel(const char* patchlevel_str) {
106cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    regex_t regex;
107cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    if (regcomp(&regex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
108cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        ALOGE("Failed to compile platform patchlevel regex! (%s)", kPlatformPatchlevelRegex);
109cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        return 0;
110cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    }
111cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
112cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    regmatch_t matches[kPlatformPatchlevelMatchCount];
11323fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    int not_match =
11423fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden        regexec(&regex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
11538837e9dbf0be3f0f6014e66c6d92a75205b964eThurston Hou Yeen Dang    regfree(&regex);
11638837e9dbf0be3f0f6014e66c6d92a75205b964eThurston Hou Yeen Dang    if (not_match) {
117cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        ALOGI("Platform patchlevel string does not match expected format.  Using patchlevel 0");
118cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        return 0;
119cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    }
120cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
121cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
122cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
123cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
124cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    if (month < 1 || month > 12) {
125cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        ALOGE("Invalid patch month %d", month);
126cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden        return 0;
127cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    }
128cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden    return year * 100 + month;
129cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden}
130cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden
13123fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willdenuint32_t GetOsPatchlevel() {
13223fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    char patchlevel_str[PROPERTY_VALUE_MAX];
13323fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    property_get(kPlatformPatchlevelProp, patchlevel_str, "" /* default */);
13423fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden    return GetOsPatchlevel(patchlevel_str);
13523fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden}
13623fe27baf78f53a44281f6f0f4169413e8770a72Shawn Willden
137cddf3a443abf64f3d77c48886693179c0b8a35bbShawn Willden}  // namespace keymaster
138