Add GetVersion to GoogleKeymaster implementation.

The GetVersion command will be used by the GoogleKeymaster HAL
implementation to verify that HAL implementation and keymaster
implementation are compatible.  Note that the GetVersion API is not
exposed through the HAL, and there's no requirement that other keymaster
implementations provide versioning (it's a good idea, though).

Bug: 18409838
Change-Id: Ia081404991b1f0f75b0e937058363d95c3e4213c
diff --git a/google_keymaster.cpp b/google_keymaster.cpp
index d1280a6..8bf1974 100644
--- a/google_keymaster.cpp
+++ b/google_keymaster.cpp
@@ -34,6 +34,10 @@
 
 namespace keymaster {
 
+const uint8_t MAJOR_VER = 1;
+const uint8_t MINOR_VER = 0;
+const uint8_t SUBMINOR_VER = 0;
+
 GoogleKeymaster::GoogleKeymaster(size_t operation_table_size, Logger* logger)
     : operation_table_(new OpTableEntry[operation_table_size]),
       operation_table_size_(operation_table_size), logger_(logger) {
@@ -70,6 +74,16 @@
     return true;
 }
 
+void GoogleKeymaster::GetVersion(const GetVersionRequest&, GetVersionResponse* rsp) {
+    if (rsp == NULL)
+        return;
+
+    rsp->major_ver = MAJOR_VER;
+    rsp->minor_ver = MINOR_VER;
+    rsp->subminor_ver = SUBMINOR_VER;
+    rsp->error = KM_ERROR_OK;
+}
+
 void GoogleKeymaster::SupportedAlgorithms(
     SupportedResponse<keymaster_algorithm_t>* response) const {
     if (response == NULL)
diff --git a/google_keymaster_messages.cpp b/google_keymaster_messages.cpp
index 90c22f4..79e7e1b 100644
--- a/google_keymaster_messages.cpp
+++ b/google_keymaster_messages.cpp
@@ -336,4 +336,30 @@
     return true;
 }
 
+size_t GetVersionResponse::NonErrorSerializedSize() const {
+    return sizeof(major_ver) + sizeof(minor_ver) + sizeof(subminor_ver);
+}
+
+uint8_t* GetVersionResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
+    if (buf + NonErrorSerializedSize() <= end) {
+        *buf++ = major_ver;
+        *buf++ = minor_ver;
+        *buf++ = subminor_ver;
+    } else {
+        buf += NonErrorSerializedSize();
+    }
+    return buf;
+}
+
+bool GetVersionResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
+    if (*buf_ptr + NonErrorSerializedSize() > end)
+        return false;
+    const uint8_t* tmp = *buf_ptr;
+    major_ver = *tmp++;
+    minor_ver = *tmp++;
+    subminor_ver = *tmp++;
+    *buf_ptr = tmp;
+    return true;
+}
+
 }  // namespace keymaster
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index adc931e..f6ee1d0 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -1135,5 +1135,16 @@
     EXPECT_EQ(0, result.size());
 }
 
+typedef KeymasterTest VersionTest;
+TEST_F(VersionTest, GetVersion) {
+    GetVersionRequest req;
+    GetVersionResponse rsp;
+    device.GetVersion(req, &rsp);
+    EXPECT_EQ(KM_ERROR_OK, rsp.error);
+    EXPECT_EQ(1, rsp.major_ver);
+    EXPECT_EQ(0, rsp.minor_ver);
+    EXPECT_EQ(0, rsp.subminor_ver);
+}
+
 }  // namespace test
 }  // namespace keymaster
diff --git a/include/keymaster/google_keymaster.h b/include/keymaster/google_keymaster.h
index 92e93d1..e340ff5 100644
--- a/include/keymaster/google_keymaster.h
+++ b/include/keymaster/google_keymaster.h
@@ -76,6 +76,7 @@
     void UpdateOperation(const UpdateOperationRequest& request, UpdateOperationResponse* response);
     void FinishOperation(const FinishOperationRequest& request, FinishOperationResponse* response);
     keymaster_error_t AbortOperation(const keymaster_operation_handle_t op_handle);
+    void GetVersion(const GetVersionRequest& request, GetVersionResponse* response);
 
     const Logger& logger() const { return *logger_; }
 
diff --git a/include/keymaster/google_keymaster_messages.h b/include/keymaster/google_keymaster_messages.h
index 622d791..fe08395 100644
--- a/include/keymaster/google_keymaster_messages.h
+++ b/include/keymaster/google_keymaster_messages.h
@@ -33,6 +33,7 @@
 const uint32_t ABORT_OPERATION = 4;
 const uint32_t IMPORT_KEY = 5;
 const uint32_t EXPORT_KEY = 6;
+const uint32_t GET_VERSION = 7;
 
 /**
  * All responses include an error value, and if the error is not KM_ERROR_OK, return no additional
@@ -41,6 +42,8 @@
  * structure, but in this case it's the cleanest option.
  */
 struct KeymasterResponse : public Serializable {
+    KeymasterResponse() : error(KM_ERROR_UNKNOWN_ERROR) {}
+
     size_t SerializedSize() const;
     uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const;
     bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end);
@@ -68,7 +71,7 @@
     SupportedResponse() : results(NULL), results_length(0) {}
     ~SupportedResponse() { delete[] results; }
 
-    template <size_t N> void SetResults(const T (&arr)[N]) {
+    template <size_t N> void SetResults(const T(&arr)[N]) {
         delete[] results;
         results_length = 0;
         results = dup_array(arr);
@@ -292,6 +295,24 @@
     size_t key_data_length;
 };
 
+struct GetVersionRequest : public Serializable {
+    size_t SerializedSize() const { return 0; }
+    uint8_t* Serialize(uint8_t* buf, const uint8_t*) const { return buf; }
+    bool Deserialize(const uint8_t**, const uint8_t*) { return true; };
+};
+
+struct GetVersionResponse : public KeymasterResponse {
+    GetVersionResponse() : major_ver(0), minor_ver(0), subminor_ver(0) {}
+
+    size_t NonErrorSerializedSize() const;
+    uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const;
+    bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end);
+
+    uint8_t major_ver;
+    uint8_t minor_ver;
+    uint8_t subminor_ver;
+};
+
 // The structs below are trivial because they're not implemented yet.
 struct RescopeRequest : public Serializable {};
 struct RescopeResponse : public KeymasterResponse {};
diff --git a/include/keymaster/keymaster_defs.h b/include/keymaster/keymaster_defs.h
index ce5cbc9..7696a61 100644
--- a/include/keymaster/keymaster_defs.h
+++ b/include/keymaster/keymaster_defs.h
@@ -374,6 +374,7 @@
     KM_ERROR_SECURE_HW_COMMUNICATION_FAILED = -49,
     KM_ERROR_UNSUPPORTED_EC_FIELD = -50,
     KM_ERROR_UNIMPLEMENTED = -100,
+    KM_ERROR_VERSION_MISMATCH = -101,
 
     /* Additional error codes may be added by implementations, but implementers should coordinate
      * with Google to avoid code collision. */