Merge "mini-keyctl: support printing security label" am: 9555bd40ce
am: 67111febbe

Change-Id: I3bb4f2f28d6527070c986720d183dc0fa1571052
diff --git a/libkeyutils/mini_keyctl.cpp b/libkeyutils/mini_keyctl.cpp
index 4fe4c3c..844f873 100644
--- a/libkeyutils/mini_keyctl.cpp
+++ b/libkeyutils/mini_keyctl.cpp
@@ -20,8 +20,11 @@
 
 #include "mini_keyctl_utils.h"
 
+#include <stdio.h>
 #include <unistd.h>
 
+#include <android-base/parseint.h>
+
 static void Usage(int exit_code) {
   fprintf(stderr, "usage: mini-keyctl <action> [args,]\n");
   fprintf(stderr, "       mini-keyctl add <type> <desc> <data> <keyring>\n");
@@ -29,6 +32,7 @@
   fprintf(stderr, "       mini-keyctl dadd <type> <desc_prefix> <cert_dir> <keyring>\n");
   fprintf(stderr, "       mini-keyctl unlink <key> <keyring>\n");
   fprintf(stderr, "       mini-keyctl restrict_keyring <keyring>\n");
+  fprintf(stderr, "       mini-keyctl security <key>\n");
   _exit(exit_code);
 }
 
@@ -66,7 +70,23 @@
     key_serial_t key = std::stoi(argv[2], nullptr, 16);
     const std::string keyring = argv[3];
     return Unlink(key, keyring);
+  } else if (action == "security") {
+    if (argc != 3) Usage(1);
+    const char* key_str = argv[2];
+    key_serial_t key;
+    if (!android::base::ParseInt(key_str, &key)) {
+      fprintf(stderr, "Unparsable key: '%s'\n", key_str);
+      return 1;
+    }
+    std::string context = RetrieveSecurityContext(key);
+    if (context.empty()) {
+      perror(key_str);
+      return 1;
+    }
+    fprintf(stderr, "%s\n", context.c_str());
+    return 0;
   } else {
+    fprintf(stderr, "Unrecognized action: %s\n", action.c_str());
     Usage(1);
   }
 
diff --git a/libkeyutils/mini_keyctl_utils.cpp b/libkeyutils/mini_keyctl_utils.cpp
index c4fc96c..3651606 100644
--- a/libkeyutils/mini_keyctl_utils.cpp
+++ b/libkeyutils/mini_keyctl_utils.cpp
@@ -210,3 +210,21 @@
   }
   return 0;
 }
+
+std::string RetrieveSecurityContext(key_serial_t key) {
+  // Simply assume this size is enough in practice.
+  const int kMaxSupportedSize = 256;
+  std::string context;
+  context.resize(kMaxSupportedSize);
+  long retval = keyctl_get_security(key, context.data(), kMaxSupportedSize);
+  if (retval < 0) {
+    PLOG(ERROR) << "Cannot get security context of key 0x" << std::hex << key;
+    return std::string();
+  }
+  if (retval > kMaxSupportedSize) {
+    LOG(ERROR) << "The key has unexpectedly long security context than " << kMaxSupportedSize;
+    return std::string();
+  }
+  context.resize(retval);
+  return context;
+}
diff --git a/libkeyutils/mini_keyctl_utils.h b/libkeyutils/mini_keyctl_utils.h
index 3c69611..150967d 100644
--- a/libkeyutils/mini_keyctl_utils.h
+++ b/libkeyutils/mini_keyctl_utils.h
@@ -46,3 +46,6 @@
 // information in the descritption section depending on the key type, only the first word in the
 // keyring description is used for searching.
 bool GetKeyringId(const std::string& keyring_desc, key_serial_t* keyring_id);
+
+// Retrieves a key's security context. Return the context string, or empty string on error.
+std::string RetrieveSecurityContext(key_serial_t key);