Change KeyParameters to use a union.

AIDL now supports union types.  This CL changes KeyParameter to use
one.

Test: VtsAidlKeyMintTargetTest
Change-Id: I5112611b161e3de1ea86105ea3c7ed0912036a7b
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
deleted file mode 100644
index 83b7e6e..0000000
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
-//
-// You must not make a backward incompatible changes to the AIDL files built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
-  NONE = 0,
-  RFC5869_SHA256 = 1,
-  ISO18033_2_KDF1_SHA1 = 2,
-  ISO18033_2_KDF1_SHA256 = 3,
-  ISO18033_2_KDF2_SHA1 = 4,
-  ISO18033_2_KDF2_SHA256 = 5,
-}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
index 91f83e4..4985768 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
@@ -16,11 +16,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
-@VintfStability
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable KeyParameter {
   android.hardware.security.keymint.Tag tag;
-  boolean boolValue;
-  int integer;
-  long longInteger;
-  byte[] blob;
+  android.hardware.security.keymint.KeyParameterValue value;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
new file mode 100644
index 0000000..ecf20ad
--- /dev/null
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.keymint;
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+union KeyParameterValue {
+  int invalid;
+  android.hardware.security.keymint.Algorithm algorithm;
+  android.hardware.security.keymint.BlockMode blockMode;
+  android.hardware.security.keymint.PaddingMode paddingMode;
+  android.hardware.security.keymint.Digest digest;
+  android.hardware.security.keymint.EcCurve ecCurve;
+  android.hardware.security.keymint.KeyOrigin origin;
+  android.hardware.security.keymint.KeyPurpose keyPurpose;
+  android.hardware.security.keymint.HardwareAuthenticatorType hardwareAuthenticatorType;
+  android.hardware.security.keymint.SecurityLevel securityLevel;
+  boolean boolValue;
+  int integer;
+  long longInteger;
+  long dateTime;
+  byte[] blob;
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl
deleted file mode 100644
index e166ab6..0000000
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-package android.hardware.security.keymint;
-
-/**
- * Key derivation functions, mostly used in ECIES.
- */
-@VintfStability
-@Backing(type="int")
-enum KeyDerivationFunction {
-    /** Do not apply a key derivation function; use the raw agreed key */
-    NONE = 0,
-    /** HKDF defined in RFC 5869 with SHA256 */
-    RFC5869_SHA256 = 1,
-    /** KDF1 defined in ISO 18033-2 with SHA1 */
-    ISO18033_2_KDF1_SHA1 = 2,
-    /** KDF1 defined in ISO 18033-2 with SHA256 */
-    ISO18033_2_KDF1_SHA256 = 3,
-    /** KDF2 defined in ISO 18033-2 with SHA1 */
-    ISO18033_2_KDF2_SHA1 = 4,
-    /** KDF2 defined in ISO 18033-2 with SHA256 */
-    ISO18033_2_KDF2_SHA256 = 5,
-}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
index 938064c..f3ed96b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
@@ -16,40 +16,16 @@
 
 package android.hardware.security.keymint;
 
-import android.hardware.security.keymint.Algorithm;
-import android.hardware.security.keymint.BlockMode;
-import android.hardware.security.keymint.Digest;
-import android.hardware.security.keymint.EcCurve;
-import android.hardware.security.keymint.HardwareAuthenticatorType;
-import android.hardware.security.keymint.KeyDerivationFunction;
-import android.hardware.security.keymint.KeyOrigin;
-import android.hardware.security.keymint.KeyPurpose;
-import android.hardware.security.keymint.PaddingMode;
-import android.hardware.security.keymint.SecurityLevel;
 import android.hardware.security.keymint.Tag;
-
+import android.hardware.security.keymint.KeyParameterValue;
 
 /**
  * Identifies the key authorization parameters to be used with keyMint.  This is usually
  * provided as an array of KeyParameters to IKeyMintDevice or Operation.
- *
- * TODO(seleneh): Union was not supported in aidl when this cl is first drafted.  So we just had
- * the Tags, and bool, int, long, int[], and we will cast to the appropate types base on the
- * Tag value.  We need to update this defination to distingish Algorithm, BlockMode,
- * PaddingMode, KeyOrigin...etc later, as union support is recently added to aidl.
- * b/173253030
  */
 @VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable KeyParameter {
-    /**
-     * Identify what type of key parameter this parcelable actually holds, and based on the type
-     * of tag is int, long, bool, or byte[], one of the fields below will be referenced.
-     */
     Tag tag;
-
-    boolean boolValue;
-    int integer;
-    long longInteger;
-    // TODO: change this to nullable.
-    byte[] blob;
+    KeyParameterValue value;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
new file mode 100644
index 0000000..a4f5154
--- /dev/null
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package android.hardware.security.keymint;
+
+import android.hardware.security.keymint.Algorithm;
+import android.hardware.security.keymint.BlockMode;
+import android.hardware.security.keymint.Digest;
+import android.hardware.security.keymint.EcCurve;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
+import android.hardware.security.keymint.KeyOrigin;
+import android.hardware.security.keymint.KeyPurpose;
+import android.hardware.security.keymint.PaddingMode;
+import android.hardware.security.keymint.SecurityLevel;
+
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+union KeyParameterValue {
+
+    /* Represents an invalid value type. */
+    int invalid;
+
+    /* Enum types */
+    Algorithm algorithm;
+    BlockMode blockMode;
+    PaddingMode paddingMode;
+    Digest digest;
+    EcCurve ecCurve;
+    KeyOrigin origin;
+    KeyPurpose keyPurpose;
+    HardwareAuthenticatorType hardwareAuthenticatorType;
+    SecurityLevel securityLevel;
+
+    /* Other types */
+    boolean boolValue;  // Always true, if present.
+    int integer;
+    long longInteger;
+    long dateTime;
+
+    byte[] blob;
+}
diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index 4e3d7ff..c443c53 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -141,72 +141,73 @@
 template <typename TypedTagType>
 struct TypedTag2ValueType;
 
-#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                              \
-    template <Tag tag>                                                             \
-    struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                           \
-        typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type;    \
-    };                                                                             \
-    template <Tag tag>                                                             \
-    inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
-            ->const decltype(param.field_name)& {                                  \
-        return param.field_name;                                                   \
-    }                                                                              \
-    template <Tag tag>                                                             \
-    inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param)       \
-            ->decltype(param.field_name)& {                                        \
-        return param.field_name;                                                   \
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                                     \
+    template <Tag tag>                                                                    \
+    struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                                  \
+        using type = std::remove_reference<decltype(                                      \
+                static_cast<KeyParameterValue*>(nullptr)                                  \
+                        ->get<KeyParameterValue::field_name>())>::type;                   \
+        static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
+    };                                                                                    \
+    template <Tag tag>                                                                    \
+    inline auto& accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) {     \
+        return param.value.get<KeyParameterValue::field_name>();                          \
+    }                                                                                     \
+    template <Tag tag>                                                                    \
+    inline auto& accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) {           \
+        return param.value.get<KeyParameterValue::field_name>();                          \
     }
 
 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, longInteger)
 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, longInteger)
-MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, dateTime)
 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, integer)
 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, integer)
 MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, boolValue)
 MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
 MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
 
-//  TODO(seleneh) change these MAKE_TAG_ENUM_VALUE_ACCESSOR back to the 2 parameter
-//  version when aidl supports union
-#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name, field_type)                 \
-    template <>                                                                         \
-    struct TypedTag2ValueType<decltype(typed_tag)> {                                    \
-        typedef field_type type;                                                        \
-    };                                                                                  \
-    inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param)          \
-            ->const field_type& {                                                       \
-        return *reinterpret_cast<const field_type*>(&param.field_name);                 \
-    }                                                                                   \
-    inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)->field_type& { \
-        return *reinterpret_cast<field_type*>(&param.field_name);                       \
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name)                               \
+    template <>                                                                           \
+    struct TypedTag2ValueType<decltype(typed_tag)> {                                      \
+        using type = std::remove_reference<decltype(                                      \
+                static_cast<KeyParameterValue*>(nullptr)                                  \
+                        ->get<KeyParameterValue::field_name>())>::type;                   \
+        static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
+    };                                                                                    \
+    inline auto& accessTagValue(decltype(typed_tag), const KeyParameter& param) {         \
+        return param.value.get<KeyParameterValue::field_name>();                          \
+    }                                                                                     \
+    inline auto& accessTagValue(decltype(typed_tag), KeyParameter& param) {               \
+        return param.value.get<KeyParameterValue::field_name>();                          \
     }
 
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, integer, Algorithm)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, integer, BlockMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, integer, Digest)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, integer, EcCurve)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, integer, KeyOrigin)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, integer, PaddingMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, integer, KeyPurpose)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, integer, HardwareAuthenticatorType)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, integer, SecurityLevel)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, algorithm)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, blockMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, digest)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, ecCurve)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, origin)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, paddingMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, keyPurpose)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, hardwareAuthenticatorType)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, securityLevel)
 
 template <TagType tag_type, Tag tag, typename ValueT>
 inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
-    KeyParameter param;
-    param.tag = tag;
-    param.longInteger = 0;
-    accessTagValue(ttag, param) = std::forward<ValueT>(value);
-    return param;
+    KeyParameter retval;
+    retval.tag = tag;
+    retval.value = KeyParameterValue::make<TypedTag2ValueType<decltype(ttag)>::unionTag>(
+            std::forward<ValueT>(value));
+    return retval;
 }
 
 // the boolean case
 template <Tag tag>
 inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
-    KeyParameter param;
-    param.tag = tag;
-    param.boolValue = true;
-    return param;
+    KeyParameter retval;
+    retval.tag = tag;
+    retval.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
+    return retval;
 }
 
 template <typename... Pack>
@@ -321,7 +322,7 @@
 template <TagType tag_type, Tag tag>
 inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> authorizationValue(
         TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
-    if (tag != param.tag) return {};
+    if (TypedTag2ValueType<TypedTag<tag_type, tag>>::unionTag != param.value.getTag()) return {};
     return accessTagValue(ttag, param);
 }
 
diff --git a/security/keymint/support/key_param_output.cpp b/security/keymint/support/key_param_output.cpp
index c56e035..0950eb6 100644
--- a/security/keymint/support/key_param_output.cpp
+++ b/security/keymint/support/key_param_output.cpp
@@ -35,38 +35,8 @@
     return os;
 }
 
-// TODO(seleneh) update this to a parsing that looks at each tags individually
-// such as ALGORITHM BLOCK_MODE when aidl union support is added.
 ostream& operator<<(ostream& os, const KeyParameter& param) {
-    os << param.tag << ": ";
-    switch (typeFromTag(param.tag)) {
-        case TagType::INVALID:
-            return os << " Invalid";
-        case TagType::ENUM_REP:
-        case TagType::ENUM:
-        case TagType::UINT_REP:
-        case TagType::UINT:
-            return os << param.integer;
-        case TagType::ULONG_REP:
-        case TagType::ULONG:
-        case TagType::DATE:
-            return os << param.longInteger;
-        case TagType::BOOL:
-            return os << "true";
-        case TagType::BIGNUM:
-            os << " Bignum: ";
-            for (size_t i = 0; i < param.blob.size(); ++i) {
-                os << std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
-            }
-            return os;
-        case TagType::BYTES:
-            os << " Bytes: ";
-            for (size_t i = 0; i < param.blob.size(); ++i) {
-                os << ::std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
-            }
-            return os;
-    }
-    return os << "UNKNOWN TAG TYPE!";
+    return os << param.toString();
 }
 
 }  // namespace aidl::android::hardware::security::keymint