Merge "Keystore 2.0: Legacy support: Tweak to certificate generation."
diff --git a/keystore2/src/crypto/certificate_utils.cpp b/keystore2/src/crypto/certificate_utils.cpp
index 500600f..4b0dca4 100644
--- a/keystore2/src/crypto/certificate_utils.cpp
+++ b/keystore2/src/crypto/certificate_utils.cpp
@@ -544,6 +544,9 @@
 
     bssl::UniquePtr<uint8_t> free_cert_buf(cert_buf);
     auto signature = sign(cert_buf, buf_len);
+    if (signature.empty()) {
+        return CertUtilsError::SignatureFailed;
+    }
 
     if (!ASN1_STRING_set(certificate->signature, signature.data(), signature.size())) {
         return CertUtilsError::BoringSsl;
diff --git a/keystore2/src/crypto/include/certificate_utils.h b/keystore2/src/crypto/include/certificate_utils.h
index 9d41eb8..1e80d80 100644
--- a/keystore2/src/crypto/include/certificate_utils.h
+++ b/keystore2/src/crypto/include/certificate_utils.h
@@ -52,6 +52,7 @@
         MemoryAllocation,
         InvalidArgument,
         UnexpectedNullPointer,
+        SignatureFailed,
     };
 
   private:
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index d965922..a27bfd1 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -19,6 +19,7 @@
 #include "km_compat_type_conversion.h"
 #include <aidl/android/hardware/security/keymint/Algorithm.h>
 #include <aidl/android/hardware/security/keymint/Digest.h>
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
 #include <aidl/android/hardware/security/keymint/PaddingMode.h>
 #include <aidl/android/system/keystore2/ResponseCode.h>
 #include <android-base/logging.h>
@@ -59,6 +60,14 @@
     return ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(result));
 }
 
+static V4_0_ErrorCode toErrorCode(const ScopedAStatus& status) {
+    if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+        return static_cast<V4_0_ErrorCode>(status.getServiceSpecificError());
+    } else {
+        return V4_0_ErrorCode::UNKNOWN_ERROR;
+    }
+}
+
 static std::vector<V4_0::KeyParameter>
 convertKeyParametersToLegacy(const std::vector<KeyParameter>& kps) {
     std::vector<V4_0::KeyParameter> legacyKps(kps.size());
@@ -660,22 +669,23 @@
             BeginResult beginResult;
             auto error = begin(KeyPurpose::SIGN, keyBlob, kps, HardwareAuthToken(), &beginResult);
             if (!error.isOk()) {
-                errorCode = static_cast<V4_0_ErrorCode>(error.getServiceSpecificError());
+                errorCode = toErrorCode(error);
                 return std::vector<uint8_t>();
             }
             std::optional<KeyParameterArray> outParams;
             std::optional<ByteArray> outByte;
             int32_t status;
-            beginResult.operation->update(std::nullopt, dataVec, std::nullopt, std::nullopt,
-                                          &outParams, &outByte, &status);
-            if (!status) {
+            error = beginResult.operation->update(std::nullopt, dataVec, std::nullopt, std::nullopt,
+                                                  &outParams, &outByte, &status);
+            if (!error.isOk()) {
+                errorCode = toErrorCode(error);
                 return std::vector<uint8_t>();
             }
             std::vector<uint8_t> result;
             error = beginResult.operation->finish(std::nullopt, std::nullopt, std::nullopt,
                                                   std::nullopt, std::nullopt, &outParams, &result);
             if (!error.isOk()) {
-                errorCode = static_cast<V4_0_ErrorCode>(error.getServiceSpecificError());
+                errorCode = toErrorCode(error);
                 return std::vector<uint8_t>();
             }
             return result;
@@ -725,6 +735,7 @@
                 }
             });
         if (!result.isOk()) {
+            LOG(ERROR) << __func__ << ": Call to attestKey failed.";
             return V4_0_ErrorCode::UNKNOWN_ERROR;
         }
         if (errorCode != V4_0_ErrorCode::OK) {
@@ -743,6 +754,7 @@
     // setIssuer
     auto error = keystore::setIssuer(&*cert, &*cert, false);
     if (error) {
+        LOG(ERROR) << __func__ << ": Set issuer failed.";
         return V4_0_ErrorCode::UNKNOWN_ERROR;
     }
 
@@ -755,26 +767,27 @@
             return false;
         }) != keyParams.end();
     auto noAuthRequired = containsParam(keyParams, KMV1::TAG_NO_AUTH_REQUIRED);
-    if (canSelfSign && noAuthRequired) {
-        auto errorCode = signCertificate(keyParams, keyBlob, &*cert);
-        if (errorCode.has_value()) {
-            return errorCode.value();
-        }
-    } else {
+    // If we cannot sign because of purpose or authorization requirement,
+    if (!(canSelfSign && noAuthRequired)
+        // or if self signing fails for any other reason,
+        || signCertificate(keyParams, keyBlob, &*cert).has_value()) {
+        // we sign with ephemeral key.
         keystore::EVP_PKEY_CTX_Ptr pkey_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL));
         EVP_PKEY_keygen_init(pkey_ctx.get());
         EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx.get(), NID_X9_62_prime256v1);
         EVP_PKEY* pkey_ptr = nullptr;
         EVP_PKEY_keygen(pkey_ctx.get(), &pkey_ptr);
         error = keystore::signCert(&*cert, pkey_ptr);
-    }
-    if (error) {
-        return V4_0_ErrorCode::UNKNOWN_ERROR;
+        if (error) {
+            LOG(ERROR) << __func__ << ": signCert failed.";
+            return V4_0_ErrorCode::UNKNOWN_ERROR;
+        }
     }
 
     // encodeCert
     auto encodedCertOrError = keystore::encodeCert(&*cert);
     if (std::holds_alternative<keystore::CertUtilsError>(encodedCertOrError)) {
+        LOG(ERROR) << __func__ << ": encodeCert failed.";
         return V4_0_ErrorCode::UNKNOWN_ERROR;
     }