Handle "hidden" authorization tags correctly.

Change-Id: I9fa18f8ab465a2faa0f358e12f72daf18ca02fe7
diff --git a/google_keymaster.cpp b/google_keymaster.cpp
index 4b49d79..8723cb1 100644
--- a/google_keymaster.cpp
+++ b/google_keymaster.cpp
@@ -32,34 +32,46 @@
 
 namespace keymaster {
 
-GoogleKeymaster::GoogleKeymaster() {}
-GoogleKeymaster::~GoogleKeymaster() {}
+GoogleKeymaster::GoogleKeymaster() {
+}
+GoogleKeymaster::~GoogleKeymaster() {
+}
 
 const int RSA_DEFAULT_KEY_SIZE = 2048;
 const int RSA_DEFAULT_EXPONENT = 65537;
 
 struct BIGNUM_Delete {
-    void operator()(BIGNUM* p) const { BN_free(p); }
+    void operator()(BIGNUM* p) const {
+        BN_free(p);
+    }
 };
 typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
 
 struct RSA_Delete {
-    void operator()(RSA* p) const { RSA_free(p); }
+    void operator()(RSA* p) const {
+        RSA_free(p);
+    }
 };
 typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
 
 struct EVP_PKEY_Delete {
-    void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
+    void operator()(EVP_PKEY* p) const {
+        EVP_PKEY_free(p);
+    }
 };
 typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
 
 struct AE_CTX_Delete {
-    void operator()(ae_ctx* ctx) const { ae_free(ctx); }
+    void operator()(ae_ctx* ctx) const {
+        ae_free(ctx);
+    }
 };
 typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
 
 struct ByteArray_Delete {
-    void operator()(void* p) const { delete[] reinterpret_cast<uint8_t*>(p); }
+    void operator()(void* p) const {
+        delete[] reinterpret_cast<uint8_t*>(p);
+    }
 };
 
 /**
@@ -187,7 +199,8 @@
         return;
     response->error = KM_ERROR_OK;
 
-    if (!CopyAuthorizations(request.key_description, response))
+    AuthorizationSet hidden_auths;
+    if (!CopyAuthorizations(request.key_description, response, &hidden_auths))
         return;
 
     keymaster_algorithm_t algorithm;
@@ -197,7 +210,7 @@
     }
     switch (algorithm) {
     case KM_ALGORITHM_RSA:
-        if (!GenerateRsa(request.key_description, response))
+        if (!GenerateRsa(request.key_description, response, &hidden_auths))
             return;
         break;
     default:
@@ -206,45 +219,16 @@
     }
 }
 
-bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response, uint8_t* key_bytes,
-                                    size_t key_length) {
-    uint8_t nonce[KeyBlob::NONCE_LENGTH];
-    GenerateNonce(nonce, array_size(nonce));
-
-    keymaster_key_blob_t key_data = {key_bytes, key_length};
-    UniquePtr<KeyBlob> blob(
-        new KeyBlob(response->enforced, response->unenforced, key_data, MasterKey(), nonce));
-    if (blob.get() == NULL) {
-        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
-        return false;
-    }
-
-    if (blob->error() != KM_ERROR_OK) {
-        return blob->error();
-        return false;
-    }
-
-    size_t size = blob->SerializedSize();
-    UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
-    if (blob_bytes.get() == NULL) {
-        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
-        return false;
-    }
-    blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
-    response->key_blob.key_material_size = size;
-    response->key_blob.key_material = blob_bytes.release();
-    return true;
-}
-
-bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths,
-                                  GenerateKeyResponse* response) {
+bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
+                                  AuthorizationSet* hidden_auths) {
     uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
     if (!key_auths.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
-        AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response);
+        AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response,
+                         hidden_auths);
 
     uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
     if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
-        AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
+        AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response, hidden_auths);
 
     Unique_BIGNUM exponent(BN_new());
     Unique_RSA rsa_key(RSA_new());
@@ -281,7 +265,38 @@
     uint8_t* tmp = der_data.get();
     i2d_PrivateKey(pkey.get(), &tmp);
 
-    return CreateKeyBlob(response, der_data.get(), der_length);
+    return CreateKeyBlob(response, *hidden_auths, der_data.get(), der_length);
+}
+
+bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response,
+                                    const AuthorizationSet& hidden_auths, uint8_t* key_bytes,
+                                    size_t key_length) {
+    uint8_t nonce[KeyBlob::NONCE_LENGTH];
+    GenerateNonce(nonce, array_size(nonce));
+
+    keymaster_key_blob_t key_data = {key_bytes, key_length};
+    UniquePtr<KeyBlob> blob(new KeyBlob(response->enforced, response->unenforced, hidden_auths,
+                                        key_data, MasterKey(), nonce));
+    if (blob.get() == NULL) {
+        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return false;
+    }
+
+    if (blob->error() != KM_ERROR_OK) {
+        return blob->error();
+        return false;
+    }
+
+    size_t size = blob->SerializedSize();
+    UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
+    if (blob_bytes.get() == NULL) {
+        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return false;
+    }
+    blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
+    response->key_blob.key_material_size = size;
+    response->key_blob.key_material = blob_bytes.release();
+    return true;
 }
 
 static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
@@ -297,7 +312,8 @@
 }
 
 bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
-                                         GenerateKeyResponse* response) {
+                                         GenerateKeyResponse* response,
+                                         AuthorizationSet* hidden_auths) {
     for (size_t i = 0; i < key_description.size(); ++i) {
         switch (key_description[i].tag) {
         case KM_TAG_ROOT_OF_TRUST:
@@ -309,14 +325,15 @@
             response->error = KM_ERROR_UNSUPPORTED_TAG;
             return false;
         default:
-            AddAuthorization(key_description[i], response);
+            AddAuthorization(key_description[i], response, hidden_auths);
             break;
         }
     }
 
-    AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response);
-    AddAuthorization(Authorization(TAG_ORIGIN, origin()), response);
-    AddAuthorization(Authorization(TAG_ROOT_OF_TRUST, "SW", 2), response);
+    AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response,
+                     hidden_auths);
+    AddAuthorization(Authorization(TAG_ORIGIN, origin()), response, hidden_auths);
+    AddAuthorization(Authorization(TAG_ROOT_OF_TRUST, "SW", 2), response, hidden_auths);
 
     response->error = CheckAuthorizationSet(response->enforced);
     if (response->error != KM_ERROR_OK)
@@ -324,16 +341,29 @@
     response->error = CheckAuthorizationSet(response->unenforced);
     if (response->error != KM_ERROR_OK)
         return false;
+    response->error = CheckAuthorizationSet(*hidden_auths);
+    if (response->error != KM_ERROR_OK)
+        return false;
 
     return true;
 }
 
 void GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
-                                       GenerateKeyResponse* response) {
-    if (is_enforced(auth.tag))
-        response->enforced.push_back(auth);
-    else
-        response->unenforced.push_back(auth);
+                                       GenerateKeyResponse* response,
+                                       AuthorizationSet* hidden_auths) {
+    switch (auth.tag) {
+    case KM_TAG_ROOT_OF_TRUST:
+    case KM_TAG_APPLICATION_ID:
+    case KM_TAG_APPLICATION_DATA:
+        hidden_auths->push_back(auth);
+        break;
+    default:
+        if (is_enforced(auth.tag))
+            response->enforced.push_back(auth);
+        else
+            response->unenforced.push_back(auth);
+        break;
+    }
 }
 
 }  // namespace keymaster