1 // 2 // Copyright (C) 2015 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 "tpm_manager/server/tpm_nvram_impl.h" 18 19 #include <arpa/inet.h> 20 21 #include <string> 22 23 #include <base/logging.h> 24 #include <base/stl_util.h> 25 #include <trousers/scoped_tss_type.h> 26 27 #include "tpm_manager/common/tpm_manager.pb.h" 28 #include "tpm_manager/server/local_data_store.h" 29 #include "tpm_manager/server/tpm_util.h" 30 31 namespace tpm_manager { 32 33 using trousers::ScopedTssMemory; 34 using trousers::ScopedTssNvStore; 35 using trousers::ScopedTssPcrs; 36 37 namespace { 38 39 // PCR0 at locality 1 is used to differentiate between developed and normal 40 // mode. Restricting nvram to the PCR0 value in locality 1 prevents nvram from 41 // persisting across mode switch. 42 const unsigned int kTpmBootPCR = 0; 43 const unsigned int kTpmPCRLocality = 1; 44 45 void MapAttributesFromTpm(TPM_NV_PER_ATTRIBUTES tpm_flags, 46 std::vector<NvramSpaceAttribute>* attributes) { 47 if (tpm_flags & TPM_NV_PER_WRITEDEFINE) 48 attributes->push_back(NVRAM_PERSISTENT_WRITE_LOCK); 49 if (tpm_flags & TPM_NV_PER_WRITE_STCLEAR) 50 attributes->push_back(NVRAM_BOOT_WRITE_LOCK); 51 if (tpm_flags & TPM_NV_PER_READ_STCLEAR) 52 attributes->push_back(NVRAM_BOOT_READ_LOCK); 53 if (tpm_flags & TPM_NV_PER_AUTHWRITE) 54 attributes->push_back(NVRAM_WRITE_AUTHORIZATION); 55 if (tpm_flags & TPM_NV_PER_AUTHREAD) 56 attributes->push_back(NVRAM_READ_AUTHORIZATION); 57 if (tpm_flags & TPM_NV_PER_GLOBALLOCK) 58 attributes->push_back(NVRAM_GLOBAL_LOCK); 59 if (tpm_flags & TPM_NV_PER_PPWRITE) 60 attributes->push_back(NVRAM_PLATFORM_WRITE); 61 if (tpm_flags & TPM_NV_PER_OWNERWRITE) 62 attributes->push_back(NVRAM_OWNER_WRITE); 63 if (tpm_flags & TPM_NV_PER_OWNERREAD) 64 attributes->push_back(NVRAM_OWNER_READ); 65 } 66 67 TPM_NV_PER_ATTRIBUTES MapAttributesToTpm( 68 const std::vector<NvramSpaceAttribute>& attributes) { 69 TPM_NV_PER_ATTRIBUTES tpm_flags = 0; 70 for (auto attribute : attributes) { 71 switch (attribute) { 72 case NVRAM_PERSISTENT_WRITE_LOCK: 73 tpm_flags |= TPM_NV_PER_WRITEDEFINE; 74 break; 75 case NVRAM_BOOT_WRITE_LOCK: 76 tpm_flags |= TPM_NV_PER_WRITE_STCLEAR; 77 break; 78 case NVRAM_BOOT_READ_LOCK: 79 tpm_flags |= TPM_NV_PER_READ_STCLEAR; 80 break; 81 case NVRAM_WRITE_AUTHORIZATION: 82 tpm_flags |= TPM_NV_PER_AUTHWRITE; 83 break; 84 case NVRAM_READ_AUTHORIZATION: 85 tpm_flags |= TPM_NV_PER_AUTHREAD; 86 break; 87 case NVRAM_GLOBAL_LOCK: 88 tpm_flags |= TPM_NV_PER_GLOBALLOCK; 89 break; 90 case NVRAM_PLATFORM_WRITE: 91 tpm_flags |= TPM_NV_PER_PPWRITE; 92 break; 93 case NVRAM_OWNER_WRITE: 94 tpm_flags |= TPM_NV_PER_OWNERWRITE; 95 break; 96 case NVRAM_OWNER_READ: 97 tpm_flags |= TPM_NV_PER_OWNERREAD; 98 break; 99 default: 100 break; 101 } 102 } 103 return tpm_flags; 104 } 105 106 NvramResult MapTpmError(TSS_RESULT tpm_error) { 107 switch (TPM_ERROR(tpm_error)) { 108 case TPM_SUCCESS: 109 return NVRAM_RESULT_SUCCESS; 110 case TPM_E_BAD_PARAMETER: 111 case TPM_E_PER_NOWRITE: 112 case TPM_E_AUTH_CONFLICT: 113 return NVRAM_RESULT_INVALID_PARAMETER; 114 case TPM_E_AREA_LOCKED: 115 case TPM_E_READ_ONLY: 116 case TPM_E_WRITE_LOCKED: 117 case TPM_E_DISABLED_CMD: 118 return NVRAM_RESULT_OPERATION_DISABLED; 119 case TPM_E_AUTHFAIL: 120 case TPM_E_NO_NV_PERMISSION: 121 case TPM_E_WRONGPCRVAL: 122 return NVRAM_RESULT_ACCESS_DENIED; 123 case TPM_E_NOSPACE: 124 case TPM_E_RESOURCES: 125 case TPM_E_SIZE: 126 return NVRAM_RESULT_INSUFFICIENT_SPACE; 127 case TPM_E_BADINDEX: 128 case TPM_E_BAD_HANDLE: 129 return NVRAM_RESULT_SPACE_DOES_NOT_EXIST; 130 } 131 return NVRAM_RESULT_DEVICE_ERROR; 132 } 133 134 } // namespace 135 136 TpmNvramImpl::TpmNvramImpl(LocalDataStore* local_data_store) 137 : local_data_store_(local_data_store) {} 138 139 NvramResult TpmNvramImpl::DefineSpace( 140 uint32_t index, 141 size_t size, 142 const std::vector<NvramSpaceAttribute>& attributes, 143 const std::string& authorization_value, 144 NvramSpacePolicy policy) { 145 std::string owner_password; 146 if (!GetOwnerPassword(&owner_password)) { 147 return NVRAM_RESULT_OPERATION_DISABLED; 148 } 149 TpmConnection owner_connection(owner_password); 150 ScopedTssNvStore nv_handle(owner_connection.GetContext()); 151 if (!InitializeNvramHandle(index, &nv_handle, &owner_connection)) { 152 return NVRAM_RESULT_DEVICE_ERROR; 153 } 154 TSS_RESULT result; 155 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_DATASIZE, 0, size); 156 if (TPM_ERROR(result)) { 157 TPM_LOG(ERROR, result) << "Could not set size on NVRAM object: " << size; 158 return NVRAM_RESULT_DEVICE_ERROR; 159 } 160 // Set permissions attributes. 161 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS, 0, 162 MapAttributesToTpm(attributes)); 163 if (TPM_ERROR(result)) { 164 TPM_LOG(ERROR, result) << "Could not set permissions on NVRAM object"; 165 return NVRAM_RESULT_DEVICE_ERROR; 166 } 167 // Set authorization. 168 if (!authorization_value.empty() && 169 !SetUsagePolicy(authorization_value, &nv_handle, &owner_connection)) { 170 return NVRAM_RESULT_DEVICE_ERROR; 171 } 172 // Bind to PCR0. 173 TSS_HPCRS pcr_handle = 0; 174 ScopedTssPcrs scoped_pcr_handle(owner_connection.GetContext()); 175 if (policy == NVRAM_POLICY_PCR0) { 176 if (!SetCompositePcr0(&scoped_pcr_handle, &owner_connection)) { 177 return NVRAM_RESULT_DEVICE_ERROR; 178 } 179 pcr_handle = scoped_pcr_handle; 180 } 181 result = Tspi_NV_DefineSpace(nv_handle, pcr_handle, /*Read*/ 182 pcr_handle /*Write*/); 183 if (TPM_ERROR(result)) { 184 TPM_LOG(ERROR, result) << "Could not define NVRAM space: " << index; 185 return MapTpmError(result); 186 } 187 return NVRAM_RESULT_SUCCESS; 188 } 189 190 NvramResult TpmNvramImpl::DestroySpace(uint32_t index) { 191 std::string owner_password; 192 if (!GetOwnerPassword(&owner_password)) { 193 return NVRAM_RESULT_OPERATION_DISABLED; 194 } 195 TpmConnection owner_connection(owner_password); 196 ScopedTssNvStore nv_handle(owner_connection.GetContext()); 197 if (!InitializeNvramHandle(index, &nv_handle, &owner_connection)) { 198 return NVRAM_RESULT_DEVICE_ERROR; 199 } 200 TSS_RESULT result = Tspi_NV_ReleaseSpace(nv_handle); 201 if (TPM_ERROR(result)) { 202 TPM_LOG(ERROR, result) << "Could not release NVRAM space: " << index; 203 return MapTpmError(result); 204 } 205 return NVRAM_RESULT_SUCCESS; 206 } 207 208 NvramResult TpmNvramImpl::WriteSpace(uint32_t index, 209 const std::string& data, 210 const std::string& authorization_value) { 211 std::vector<NvramSpaceAttribute> attributes; 212 NvramResult result = 213 GetSpaceInfo(index, nullptr, nullptr, nullptr, &attributes, nullptr); 214 if (result != NVRAM_RESULT_SUCCESS) { 215 return result; 216 } 217 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 218 if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) { 219 return NVRAM_RESULT_DEVICE_ERROR; 220 } 221 for (const auto& attribute : attributes) { 222 if (attribute == NVRAM_OWNER_WRITE) { 223 if (!SetOwnerPolicy(&nv_handle)) { 224 return NVRAM_RESULT_OPERATION_DISABLED; 225 } 226 break; 227 } 228 if (attribute == NVRAM_WRITE_AUTHORIZATION) { 229 if (!SetUsagePolicy(authorization_value, &nv_handle, &tpm_connection_)) { 230 return NVRAM_RESULT_DEVICE_ERROR; 231 } 232 break; 233 } 234 } 235 TSS_RESULT tpm_result = Tspi_NV_WriteValue( 236 nv_handle, 0 /* offset */, data.size(), 237 reinterpret_cast<BYTE*>(const_cast<char*>(data.data()))); 238 if (TPM_ERROR(tpm_result)) { 239 TPM_LOG(ERROR, tpm_result) << "Could not write to NVRAM space: " << index; 240 return MapTpmError(tpm_result); 241 } 242 return NVRAM_RESULT_SUCCESS; 243 } 244 245 NvramResult TpmNvramImpl::ReadSpace(uint32_t index, 246 std::string* data, 247 const std::string& authorization_value) { 248 CHECK(data); 249 size_t nvram_size; 250 std::vector<NvramSpaceAttribute> attributes; 251 NvramResult result = 252 GetSpaceInfo(index, &nvram_size, nullptr, nullptr, &attributes, nullptr); 253 if (result != NVRAM_RESULT_SUCCESS) { 254 return result; 255 } 256 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 257 if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) { 258 return NVRAM_RESULT_DEVICE_ERROR; 259 } 260 for (const auto& attribute : attributes) { 261 if (attribute == NVRAM_OWNER_READ) { 262 if (!SetOwnerPolicy(&nv_handle)) { 263 return NVRAM_RESULT_OPERATION_DISABLED; 264 } 265 break; 266 } 267 if (attribute == NVRAM_READ_AUTHORIZATION) { 268 if (!SetUsagePolicy(authorization_value, &nv_handle, &tpm_connection_)) { 269 return NVRAM_RESULT_DEVICE_ERROR; 270 } 271 break; 272 } 273 } 274 data->resize(nvram_size); 275 // The Tpm1.2 Specification defines the maximum read size of 128 bytes. 276 // Therefore we have to loop through the data returned. 277 const size_t kMaxDataSize = 128; 278 uint32_t offset = 0; 279 while (offset < nvram_size) { 280 uint32_t chunk_size = std::min(nvram_size - offset, kMaxDataSize); 281 ScopedTssMemory space_data(tpm_connection_.GetContext()); 282 TSS_RESULT tpm_result = 283 Tspi_NV_ReadValue(nv_handle, offset, &chunk_size, space_data.ptr()); 284 if (TPM_ERROR(tpm_result)) { 285 TPM_LOG(ERROR, tpm_result) << "Could not read from NVRAM space: " 286 << index; 287 data->clear(); 288 return MapTpmError(tpm_result); 289 } 290 if (!space_data.value()) { 291 LOG(ERROR) << "No data read from NVRAM space: " << index; 292 data->clear(); 293 return NVRAM_RESULT_DEVICE_ERROR; 294 } 295 CHECK_LE((offset + chunk_size), data->size()); 296 data->replace(offset, chunk_size, 297 reinterpret_cast<char*>(space_data.value()), chunk_size); 298 offset += chunk_size; 299 } 300 return NVRAM_RESULT_SUCCESS; 301 } 302 303 NvramResult TpmNvramImpl::LockSpace(uint32_t index, 304 bool lock_read, 305 bool lock_write, 306 const std::string& authorization_value) { 307 std::vector<NvramSpaceAttribute> attributes; 308 NvramResult result = 309 GetSpaceInfo(index, nullptr, nullptr, nullptr, &attributes, nullptr); 310 if (result != NVRAM_RESULT_SUCCESS) { 311 return result; 312 } 313 if (lock_read) { 314 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 315 if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) { 316 return NVRAM_RESULT_DEVICE_ERROR; 317 } 318 for (const auto& attribute : attributes) { 319 if (attribute == NVRAM_OWNER_READ) { 320 if (!SetOwnerPolicy(&nv_handle)) { 321 return NVRAM_RESULT_OPERATION_DISABLED; 322 } 323 break; 324 } 325 if (attribute == NVRAM_READ_AUTHORIZATION) { 326 if (!SetUsagePolicy(authorization_value, &nv_handle, 327 &tpm_connection_)) { 328 return NVRAM_RESULT_DEVICE_ERROR; 329 } 330 break; 331 } 332 } 333 uint32_t size = 0; 334 ScopedTssMemory space_data(tpm_connection_.GetContext()); 335 TSS_RESULT tpm_result = 336 Tspi_NV_ReadValue(nv_handle, 0, &size, space_data.ptr()); 337 if (TPM_ERROR(tpm_result)) { 338 TPM_LOG(ERROR, tpm_result) << "Could not lock read for NVRAM space: " 339 << index; 340 return MapTpmError(tpm_result); 341 } 342 } 343 if (lock_write) { 344 ScopedTssNvStore nv_handle(tpm_connection_.GetContext()); 345 if (!InitializeNvramHandle(index, &nv_handle, &tpm_connection_)) { 346 return NVRAM_RESULT_DEVICE_ERROR; 347 } 348 for (const auto& attribute : attributes) { 349 if (attribute == NVRAM_OWNER_WRITE) { 350 if (!SetOwnerPolicy(&nv_handle)) { 351 return NVRAM_RESULT_OPERATION_DISABLED; 352 } 353 break; 354 } 355 if (attribute == NVRAM_WRITE_AUTHORIZATION) { 356 if (!SetUsagePolicy(authorization_value, &nv_handle, 357 &tpm_connection_)) { 358 return NVRAM_RESULT_DEVICE_ERROR; 359 } 360 break; 361 } 362 } 363 BYTE not_used; 364 TSS_RESULT tpm_result = Tspi_NV_WriteValue(nv_handle, 0, 0, ¬_used); 365 if (TPM_ERROR(tpm_result)) { 366 TPM_LOG(ERROR, tpm_result) << "Could not lock write for NVRAM space: " 367 << index; 368 return MapTpmError(tpm_result); 369 } 370 } 371 return NVRAM_RESULT_SUCCESS; 372 } 373 374 NvramResult TpmNvramImpl::ListSpaces(std::vector<uint32_t>* index_list) { 375 uint32_t nv_list_data_length = 0; 376 ScopedTssMemory nv_list_data(tpm_connection_.GetContext()); 377 TSS_RESULT result = 378 Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), TSS_TPMCAP_NV_LIST, 0, 379 nullptr, &nv_list_data_length, nv_list_data.ptr()); 380 if (TPM_ERROR(result)) { 381 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability"; 382 return MapTpmError(result); 383 } 384 // Walk the list and check if the index exists. 385 uint32_t* nv_list = reinterpret_cast<uint32_t*>(nv_list_data.value()); 386 uint32_t nv_list_length = nv_list_data_length / sizeof(uint32_t); 387 for (uint32_t i = 0; i < nv_list_length; ++i) { 388 // TPM data is network byte order. 389 index_list->push_back(ntohl(nv_list[i])); 390 } 391 return NVRAM_RESULT_SUCCESS; 392 } 393 394 NvramResult TpmNvramImpl::GetSpaceInfo( 395 uint32_t index, 396 size_t* size, 397 bool* is_read_locked, 398 bool* is_write_locked, 399 std::vector<NvramSpaceAttribute>* attributes, 400 NvramSpacePolicy* policy) { 401 UINT32 nv_index_data_length = 0; 402 ScopedTssMemory nv_index_data(tpm_connection_.GetContext()); 403 TSS_RESULT result = 404 Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), TSS_TPMCAP_NV_INDEX, 405 sizeof(index), reinterpret_cast<BYTE*>(&index), 406 &nv_index_data_length, nv_index_data.ptr()); 407 if (TPM_ERROR(result)) { 408 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability"; 409 return MapTpmError(result); 410 } 411 UINT64 offset = 0; 412 Trspi_UnloadBlob_NV_DATA_PUBLIC(&offset, nv_index_data.value(), nullptr); 413 if (nv_index_data_length < offset) { 414 LOG(ERROR) << "Not enough data from Tspi_TPM_GetCapability."; 415 return NVRAM_RESULT_DEVICE_ERROR; 416 } 417 TPM_NV_DATA_PUBLIC info; 418 offset = 0; 419 result = 420 Trspi_UnloadBlob_NV_DATA_PUBLIC(&offset, nv_index_data.value(), &info); 421 if (TPM_ERROR(result)) { 422 TPM_LOG(ERROR, result) << "Error calling Trspi_UnloadBlob_NV_DATA_PUBLIC"; 423 return NVRAM_RESULT_DEVICE_ERROR; 424 } 425 if (size) { 426 *size = info.dataSize; 427 } 428 if (is_read_locked) { 429 *is_read_locked = info.bReadSTClear; 430 } 431 if (is_write_locked) { 432 *is_write_locked = info.bWriteSTClear || info.bWriteDefine; 433 } 434 if (attributes) { 435 MapAttributesFromTpm(info.permission.attributes, attributes); 436 } 437 if (policy) { 438 if (info.pcrInfoWrite.pcrSelection.sizeOfSelect > 0 && 439 (info.pcrInfoWrite.pcrSelection.pcrSelect[0] & 1) != 0) { 440 *policy = NVRAM_POLICY_PCR0; 441 } else { 442 *policy = NVRAM_POLICY_NONE; 443 } 444 } 445 return NVRAM_RESULT_SUCCESS; 446 } 447 448 bool TpmNvramImpl::InitializeNvramHandle(uint32_t index, 449 ScopedTssNvStore* nv_handle, 450 TpmConnection* connection) { 451 TSS_RESULT result = Tspi_Context_CreateObject( 452 connection->GetContext(), TSS_OBJECT_TYPE_NV, 0, nv_handle->ptr()); 453 if (TPM_ERROR(result)) { 454 TPM_LOG(ERROR, result) << "Could not acquire an NVRAM object handle"; 455 return false; 456 } 457 result = Tspi_SetAttribUint32(nv_handle->value(), TSS_TSPATTRIB_NV_INDEX, 0, 458 index); 459 if (TPM_ERROR(result)) { 460 TPM_LOG(ERROR, result) << "Could not set index on NVRAM object: " << index; 461 return false; 462 } 463 return true; 464 } 465 466 bool TpmNvramImpl::SetOwnerPolicy(ScopedTssNvStore* nv_handle) { 467 std::string owner_password; 468 if (!GetOwnerPassword(&owner_password)) { 469 return false; 470 } 471 return SetUsagePolicy(owner_password, nv_handle, &tpm_connection_); 472 } 473 474 bool TpmNvramImpl::SetUsagePolicy(const std::string& authorization_value, 475 trousers::ScopedTssNvStore* nv_handle, 476 TpmConnection* connection) { 477 trousers::ScopedTssPolicy policy_handle(connection->GetContext()); 478 TSS_RESULT result; 479 result = Tspi_Context_CreateObject(connection->GetContext(), 480 TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, 481 policy_handle.ptr()); 482 if (TPM_ERROR(result)) { 483 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject"; 484 return false; 485 } 486 result = Tspi_Policy_SetSecret( 487 policy_handle, TSS_SECRET_MODE_PLAIN, authorization_value.size(), 488 reinterpret_cast<BYTE*>(const_cast<char*>(authorization_value.data()))); 489 if (TPM_ERROR(result)) { 490 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret"; 491 return false; 492 } 493 result = 494 Tspi_Policy_AssignToObject(policy_handle.value(), nv_handle->value()); 495 if (TPM_ERROR(result)) { 496 TPM_LOG(ERROR, result) << "Could not set NVRAM object policy."; 497 return false; 498 } 499 return true; 500 } 501 502 bool TpmNvramImpl::SetCompositePcr0(ScopedTssPcrs* pcr_handle, 503 TpmConnection* connection) { 504 TSS_RESULT result = Tspi_Context_CreateObject( 505 connection->GetContext(), TSS_OBJECT_TYPE_PCRS, 506 TSS_PCRS_STRUCT_INFO_SHORT, pcr_handle->ptr()); 507 if (TPM_ERROR(result)) { 508 TPM_LOG(ERROR, result) << "Could not acquire PCR object handle"; 509 return false; 510 } 511 uint32_t pcr_len; 512 ScopedTssMemory pcr_value(connection->GetContext()); 513 result = Tspi_TPM_PcrRead(connection->GetTpm(), kTpmBootPCR, &pcr_len, 514 pcr_value.ptr()); 515 if (TPM_ERROR(result)) { 516 TPM_LOG(ERROR, result) << "Could not read PCR0 value"; 517 return false; 518 } 519 result = Tspi_PcrComposite_SetPcrValue(pcr_handle->value(), kTpmBootPCR, 520 pcr_len, pcr_value.value()); 521 if (TPM_ERROR(result)) { 522 TPM_LOG(ERROR, result) << "Could not set value for PCR0 in PCR handle"; 523 return false; 524 } 525 result = 526 Tspi_PcrComposite_SetPcrLocality(pcr_handle->value(), kTpmPCRLocality); 527 if (TPM_ERROR(result)) { 528 TPM_LOG(ERROR, result) << "Could not set locality for PCR0 in PCR handle"; 529 return false; 530 } 531 return true; 532 } 533 534 bool TpmNvramImpl::GetOwnerPassword(std::string* owner_password) { 535 LocalData local_data; 536 if (!local_data_store_->Read(&local_data)) { 537 LOG(ERROR) << "Error reading local data for owner password."; 538 return false; 539 } 540 if (local_data.owner_password().empty()) { 541 LOG(ERROR) << "No owner password present in tpm local_data."; 542 return false; 543 } 544 owner_password->assign(local_data.owner_password()); 545 return true; 546 } 547 548 } // namespace tpm_manager 549