1/* 2 * Copyright (C) 2016 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 <keymaster/keymaster_configuration.h> 18 19#include <regex> 20#include <string> 21 22#include <regex.h> 23 24#define LOG_TAG "keymaster" 25#include <cutils/log.h> 26 27#ifndef KEYMASTER_UNIT_TEST_BUILD 28#include <cutils/properties.h> 29#else 30#define PROPERTY_VALUE_MAX 80 /* Value doesn't matter */ 31void property_get(const char* /* prop_name */, char* /* prop */, const char* /* default */) {} 32#endif 33 34#include <keymaster/authorization_set.h> 35 36namespace keymaster { 37 38namespace { 39 40constexpr char kPlatformVersionProp[] = "ro.build.version.release"; 41constexpr char kPlatformVersionRegex[] = "^([0-9]{1,2})(\\.([0-9]{1,2}))?(\\.([0-9]{1,2}))?"; 42constexpr size_t kMajorVersionMatch = 1; 43constexpr size_t kMinorVersionMatch = 3; 44constexpr size_t kSubminorVersionMatch = 5; 45constexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1; 46 47constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch"; 48constexpr char kPlatformPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$"; 49constexpr size_t kYearMatch = 1; 50constexpr size_t kMonthMatch = 2; 51constexpr size_t kPlatformPatchlevelMatchCount = kMonthMatch + 1; 52 53uint32_t match_to_uint32(const char* expression, const regmatch_t& match) { 54 if (match.rm_so == -1) 55 return 0; 56 57 size_t len = match.rm_eo - match.rm_so; 58 std::string s(expression + match.rm_so, len); 59 return std::stoul(s); 60} 61 62} // anonymous namespace 63 64keymaster_error_t ConfigureDevice(keymaster2_device_t* dev, uint32_t os_version, 65 uint32_t os_patchlevel) { 66 AuthorizationSet config_params(AuthorizationSetBuilder() 67 .Authorization(keymaster::TAG_OS_VERSION, os_version) 68 .Authorization(keymaster::TAG_OS_PATCHLEVEL, os_patchlevel)); 69 return dev->configure(dev, &config_params); 70} 71 72keymaster_error_t ConfigureDevice(keymaster2_device_t* dev) { 73 return ConfigureDevice(dev, GetOsVersion(), GetOsPatchlevel()); 74} 75 76uint32_t GetOsVersion(const char* version_str) { 77 regex_t regex; 78 if (regcomp(®ex, kPlatformVersionRegex, REG_EXTENDED)) { 79 ALOGE("Failed to compile version regex! (%s)", kPlatformVersionRegex); 80 return 0; 81 } 82 83 regmatch_t matches[kPlatformVersionMatchCount]; 84 int not_match = 85 regexec(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */); 86 regfree(®ex); 87 if (not_match) { 88 ALOGI("Platform version string does not match expected format. Using version 0."); 89 return 0; 90 } 91 92 uint32_t major = match_to_uint32(version_str, matches[kMajorVersionMatch]); 93 uint32_t minor = match_to_uint32(version_str, matches[kMinorVersionMatch]); 94 uint32_t subminor = match_to_uint32(version_str, matches[kSubminorVersionMatch]); 95 96 return (major * 100 + minor) * 100 + subminor; 97} 98 99uint32_t GetOsVersion() { 100 char version_str[PROPERTY_VALUE_MAX]; 101 property_get(kPlatformVersionProp, version_str, "" /* default */); 102 return GetOsVersion(version_str); 103} 104 105uint32_t GetOsPatchlevel(const char* patchlevel_str) { 106 regex_t regex; 107 if (regcomp(®ex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) { 108 ALOGE("Failed to compile platform patchlevel regex! (%s)", kPlatformPatchlevelRegex); 109 return 0; 110 } 111 112 regmatch_t matches[kPlatformPatchlevelMatchCount]; 113 int not_match = 114 regexec(®ex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */); 115 regfree(®ex); 116 if (not_match) { 117 ALOGI("Platform patchlevel string does not match expected format. Using patchlevel 0"); 118 return 0; 119 } 120 121 uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]); 122 uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]); 123 124 if (month < 1 || month > 12) { 125 ALOGE("Invalid patch month %d", month); 126 return 0; 127 } 128 return year * 100 + month; 129} 130 131uint32_t GetOsPatchlevel() { 132 char patchlevel_str[PROPERTY_VALUE_MAX]; 133 property_get(kPlatformPatchlevelProp, patchlevel_str, "" /* default */); 134 return GetOsPatchlevel(patchlevel_str); 135} 136 137} // namespace keymaster 138