1 /* 2 * Copyright (C) 2018 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 <gtest/gtest.h> 18 19 #include <application.h> 20 #include <app_nugget.h> 21 #include <nos/MockNuggetClient.h> 22 23 #include <AuthSecret.h> 24 25 using ::testing::_; 26 using ::testing::ElementsAre; 27 using ::testing::Return; 28 29 using ::android::hardware::hidl_vec; 30 using ::android::hardware::authsecret::AuthSecret; 31 32 using ::nos::MockNuggetClient; 33 34 uint8_t SECRET_STRING[] = "this_password_is_fake"; 35 // sha256( "citadel_update" | 0 | secret ) 36 const uint8_t EXPECTED_PASSWORD[NUGGET_UPDATE_PASSWORD_LEN] = { 37 0x31, 0x96, 0xb6, 0x46, 0x49, 0x90, 0x17, 0xc2, 38 0x08, 0x80, 0xa6, 0x4d, 0x3f, 0x2d, 0x50, 0x9a, 39 0x3e, 0x9a, 0x25, 0xaa, 0xd7, 0xcc, 0x48, 0x5d, 40 0xd0, 0x0b, 0x8c, 0xf3, 0xcc, 0x8f, 0xfe, 0x41, 41 }; 42 // First 4 bytes of sha1 of the expectedPassword 43 constexpr uint32_t EXPECTED_PASSWORD_CHECKSUM = 0xdca3b96d; 44 45 // This is the Citadel update password if one hasn't been set 46 const uint8_t DEFUALT_PASSWORD[NUGGET_UPDATE_PASSWORD_LEN] = { 47 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 48 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 49 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 51 }; 52 constexpr uint32_t DEFUALT_PASSWORD_CHECKSUM = 0xffffffff; // uninitialized flash 53 54 // primaryUserCredential 55 56 MATCHER_P2(OldPasswordEq, pwd, checksum, "") { 57 const nugget_app_change_update_password* const msg 58 = reinterpret_cast<const nugget_app_change_update_password*>(arg.data()); 59 return memcmp(msg->old_password.password, pwd, NUGGET_UPDATE_PASSWORD_LEN) == 0 60 && msg->old_password.digest == checksum; 61 } 62 63 MATCHER_P2(NewPasswordEq, pwd, checksum, "") { 64 const nugget_app_change_update_password* const msg 65 = reinterpret_cast<const nugget_app_change_update_password*>(arg.data()); 66 return memcmp(msg->new_password.password, pwd, NUGGET_UPDATE_PASSWORD_LEN) == 0 67 && msg->new_password.digest == checksum; 68 } 69 70 TEST(AuthSecretHalTest, changePasswordFromDefault) { 71 MockNuggetClient client; 72 AuthSecret hal{client}; 73 74 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_CHANGE_UPDATE_PASSWORD, 75 OldPasswordEq(DEFUALT_PASSWORD, DEFUALT_PASSWORD_CHECKSUM), _)) 76 .WillOnce(Return(APP_SUCCESS)); 77 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_ENABLE_UPDATE, _, _)) 78 .WillOnce(Return(APP_SUCCESS)); 79 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, _, _)) 80 .WillOnce(Return(APP_SUCCESS)); 81 82 hidl_vec<uint8_t> secret; 83 secret.setToExternal(SECRET_STRING, sizeof(SECRET_STRING) - 1); 84 hal.primaryUserCredential(secret); 85 } 86 87 TEST(AuthSecretHalTest, changePasswordToDerived) { 88 MockNuggetClient client; 89 AuthSecret hal{client}; 90 91 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_CHANGE_UPDATE_PASSWORD, 92 NewPasswordEq(EXPECTED_PASSWORD, EXPECTED_PASSWORD_CHECKSUM), _)) 93 .WillOnce(Return(APP_SUCCESS)); 94 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_ENABLE_UPDATE, _, _)) 95 .WillOnce(Return(APP_SUCCESS)); 96 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, _, _)) 97 .WillOnce(Return(APP_SUCCESS)); 98 99 hidl_vec<uint8_t> secret; 100 secret.setToExternal(SECRET_STRING, sizeof(SECRET_STRING) - 1); 101 hal.primaryUserCredential(secret); 102 } 103 104 TEST(AuthSecretHalTest, whenPasswordAlreadySetAlsoTryUpdateAndReboot) { 105 MockNuggetClient client; 106 AuthSecret hal{client}; 107 108 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_CHANGE_UPDATE_PASSWORD, _, _)) 109 .WillOnce(Return(APP_ERROR_BOGUS_ARGS)); 110 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_ENABLE_UPDATE, _, _)) 111 .WillOnce(Return(APP_SUCCESS)); 112 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, _, _)) 113 .WillOnce(Return(APP_SUCCESS)); 114 115 hidl_vec<uint8_t> secret(19); 116 hal.primaryUserCredential(secret); 117 } 118 119 MATCHER_P2(UpdatePasswordEq, pwd, checksum, "") { 120 const nugget_app_enable_update* const msg 121 = reinterpret_cast<const nugget_app_enable_update*>(arg.data()); 122 return memcmp(msg->password.password, pwd, NUGGET_UPDATE_PASSWORD_LEN) == 0 123 && msg->password.digest == checksum; 124 } 125 126 MATCHER_P(WhichHeaderEq, headers, "") { 127 const nugget_app_enable_update* const msg 128 = reinterpret_cast<const nugget_app_enable_update*>(arg.data()); 129 return msg->which_headers == headers; 130 } 131 132 TEST(AuthSecretHalTest, attemptUpdateWithDerivedPassword) { 133 MockNuggetClient client; 134 AuthSecret hal{client}; 135 136 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_CHANGE_UPDATE_PASSWORD, _, _)) 137 .WillOnce(Return(APP_ERROR_BOGUS_ARGS)); 138 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_ENABLE_UPDATE, 139 UpdatePasswordEq(EXPECTED_PASSWORD, EXPECTED_PASSWORD_CHECKSUM), _)) 140 .WillOnce(Return(APP_SUCCESS)); 141 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, _, _)) 142 .WillOnce(Return(APP_SUCCESS)); 143 144 hidl_vec<uint8_t> secret; 145 secret.setToExternal(SECRET_STRING, sizeof(SECRET_STRING) - 1); 146 hal.primaryUserCredential(secret); 147 } 148 149 TEST(AuthSecretHalTest, updateRwAndRoTogether) { 150 MockNuggetClient client; 151 AuthSecret hal{client}; 152 153 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_CHANGE_UPDATE_PASSWORD, _, _)) 154 .WillOnce(Return(APP_ERROR_BOGUS_ARGS)); 155 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_ENABLE_UPDATE, 156 WhichHeaderEq(NUGGET_ENABLE_HEADER_RW | NUGGET_ENABLE_HEADER_RO), 157 _)).WillOnce(Return(APP_SUCCESS)); 158 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, 159 _, _)).WillOnce(Return(APP_SUCCESS)); 160 161 hidl_vec<uint8_t> secret(47); 162 hal.primaryUserCredential(secret); 163 } 164 165 TEST(AuthSecretHalTest, citadelDoesNotLikePasswordSoDoNotReboot) { 166 MockNuggetClient client; 167 AuthSecret hal{client}; 168 169 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_CHANGE_UPDATE_PASSWORD, _, _)) 170 .WillOnce(Return(APP_ERROR_BOGUS_ARGS)); 171 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_ENABLE_UPDATE, _, _)) 172 .WillOnce(Return(APP_ERROR_BOGUS_ARGS)); 173 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, _, _)).Times(0); 174 175 hidl_vec<uint8_t> secret(20); 176 hal.primaryUserCredential(secret); 177 // Nothing should happen, in particular it shouldn't crash 178 } 179 180 TEST(AuthSecretHalTest, updateHitAnErrorSoDoNotReboot) { 181 MockNuggetClient client; 182 AuthSecret hal{client}; 183 184 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_CHANGE_UPDATE_PASSWORD, _, _)) 185 .WillOnce(Return(APP_ERROR_BOGUS_ARGS)); 186 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_ENABLE_UPDATE, _, _)) 187 .WillOnce(Return(APP_ERROR_INTERNAL)); 188 EXPECT_CALL(client, CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, _, _)).Times(0); 189 190 hidl_vec<uint8_t> secret(32); 191 hal.primaryUserCredential(secret); 192 // Nothing should happen, in particular it shouldn't crash 193 } 194