Merge "KeyStore: Fix key name decoding" am: 41bf9b04e4 am: fd9c8781e8
am: 17c18c2e45
Change-Id: Idbd30b4b8dd273c93df7a91fd42338da36882a8c
diff --git a/keystore/Android.bp b/keystore/Android.bp
index 295d605..366f591 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -234,6 +234,7 @@
srcs: [
":IKeyAttestationApplicationIdProvider.aidl",
"auth_token_table.cpp",
+ "blob.cpp",
"keystore_attestation_id.cpp",
"KeyAttestationApplicationId.cpp",
"KeyAttestationPackageInfo.cpp",
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index f08e08d..f887e80 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -559,15 +559,23 @@
* [0-o]. Therefore in the worst case the length of a key gets doubled. Note
* that Base64 cannot be used here due to the need of prefix match on keys. */
-static std::string encodeKeyName(const std::string& keyName) {
+std::string encodeKeyName(const std::string& keyName) {
std::string encodedName;
encodedName.reserve(keyName.size() * 2);
auto in = keyName.begin();
while (in != keyName.end()) {
+ // Input character needs to be encoded.
if (*in < '0' || *in > '~') {
+ // Encode the two most-significant bits of the input char in the first
+ // output character, by counting up from 43 ('+').
encodedName.append(1, '+' + (uint8_t(*in) >> 6));
+ // Encode the six least-significant bits of the input char in the second
+ // output character, by counting up from 48 ('0').
+ // This is safe because the maximum value is 112, which is the
+ // character 'p'.
encodedName.append(1, '0' + (*in & 0x3F));
} else {
+ // No need to encode input char - append as-is.
encodedName.append(1, *in);
}
++in;
@@ -575,7 +583,7 @@
return encodedName;
}
-static std::string decodeKeyName(const std::string& encodedName) {
+std::string decodeKeyName(const std::string& encodedName) {
std::string decodedName;
decodedName.reserve(encodedName.size());
auto in = encodedName.begin();
@@ -583,12 +591,19 @@
char c;
while (in != encodedName.end()) {
if (multichar) {
+ // Second part of a multi-character encoding. Turn off the multichar
+ // flag and set the six least-significant bits of c to the value originally
+ // encoded by counting up from '0'.
multichar = false;
- decodedName.append(1, c | *in);
+ decodedName.append(1, c | (uint8_t(*in) - '0'));
} else if (*in >= '+' && *in <= '.') {
+ // First part of a multi-character encoding. Set the multichar flag
+ // and set the two most-significant bits of c to be the two bits originally
+ // encoded by counting up from '+'.
multichar = true;
c = (*in - '+') << 6;
} else {
+ // Regular character, append as-is.
decodedName.append(1, *in);
}
++in;
diff --git a/keystore/blob.h b/keystore/blob.h
index a7f9fd0..92e4514 100644
--- a/keystore/blob.h
+++ b/keystore/blob.h
@@ -272,4 +272,8 @@
inline const KeyBlobEntry* operator->() const { return entry_; }
};
+// Visible for testing
+std::string encodeKeyName(const std::string& keyName);
+std::string decodeKeyName(const std::string& encodedName);
+
#endif // KEYSTORE_BLOB_H_
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
index 103fa0e..1ce1210 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -11,6 +11,7 @@
"aaid_truncation_test.cpp",
"auth_token_table_test.cpp",
"auth_token_formatting_test.cpp",
+ "blob_test.cpp",
"confirmationui_rate_limiting_test.cpp",
"gtest_main.cpp",
],
diff --git a/keystore/tests/blob_test.cpp b/keystore/tests/blob_test.cpp
new file mode 100644
index 0000000..485bd88
--- /dev/null
+++ b/keystore/tests/blob_test.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <utils/String16.h>
+
+#include "../blob.h"
+
+namespace keystore {
+
+namespace test {
+
+namespace {
+
+constexpr const char* kNameToEncode = "some key name !\\ %#|\"";
+
+} // namespace
+
+TEST(BlobTest, nameEncodingAndDecodingTest) {
+ std::string toEncode(kNameToEncode);
+ std::string decoded(decodeKeyName(encodeKeyName(toEncode)));
+
+ ASSERT_EQ(toEncode, decoded);
+}
+
+} // namespace test
+} // namespace keystore