Return error if password is not empty and row is not password protected
[platform/core/security/key-manager.git] / src / manager / service / crypto-logic.cpp
index 10960fb..6fe6e4e 100644 (file)
@@ -22,6 +22,9 @@
 
 #include <iostream>
 #include <fstream>
+#include <utility>
+#include <climits>
+
 #include <stdio.h>
 #include <string.h>
 
 #include <generic-backend/exception.h>
 #include <sw-backend/internals.h>
 
+namespace CKM {
+
 namespace {
 
 const static int AES_CBC_KEY_SIZE = 32;
 const static int AES_GCM_TAG_SIZE = 16;
 
-} // anonymous namespace
+// Encryption scheme flags (enable/disable specific encryption type, multiple choice)
+const int ENCR_BASE64 =   1 << 0;
+const int ENCR_APPKEY =   1 << 1;
+const int ENCR_PASSWORD = 1 << 2;
 
-namespace CKM {
+// Encryption order flags (single choice)
+const int ENCR_ORDER_OFFSET = 24;
+const int ENCR_ORDER_FILTER = INT_MAX << ENCR_ORDER_OFFSET; // 0xff000000
+const int ENCR_ORDER_CLEAR = ~ENCR_ORDER_FILTER; // 0x00ffffff
+/*
+ * ENCR_ORDER_V1 - v1 encryption order. Token returned from store is encrypted with app key and
+ * optionally by custom user password. In such form it is stored in db.
+ */
+const int ENCR_ORDER_V1 = CryptoLogic::ENCRYPTION_V1 << ENCR_ORDER_OFFSET;
+/*
+ * ENCR_ORDER_V2 - v2 encryption order. Stored data is optionally encrypted by store with
+ * user password. Returned token is encrypted with app key and stored in db.
+ */
+const int ENCR_ORDER_V2 = CryptoLogic::ENCRYPTION_V2 << ENCR_ORDER_OFFSET;
+
+} // anonymous namespace
 
 CryptoLogic::CryptoLogic() {}
 
@@ -120,7 +143,7 @@ RawBuffer CryptoLogic::generateRandIV() const {
     return civ;
 }
 
-void CryptoLogic::encryptRow(const Password &password, DB::Row &row)
+void CryptoLogic::encryptRow(DB::Row &row)
 {
     try {
         DB::Row crow = row;
@@ -152,18 +175,14 @@ void CryptoLogic::encryptRow(const Password &password, DB::Row &row)
 
         crow.tag = dataPair.second;
 
-        if (!password.empty()) {
-            key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE);
-
-            crow.data = Crypto::SW::Internals::encryptDataAesCbc(key, crow.data, crow.iv);
-            crow.encryptionScheme |= ENCR_PASSWORD;
-        }
-
         encBase64(crow.data);
         crow.encryptionScheme |= ENCR_BASE64;
         encBase64(crow.iv);
 
-        row = crow;
+        crow.encryptionScheme &= ENCR_ORDER_CLEAR;
+        crow.encryptionScheme |= ENCR_ORDER_V2;
+
+        row = std::move(crow);
     } catch(const CKM::Base64Encoder::Exception::Base &e) {
         ThrowErr(Exc::InternalError, e.GetMessage());
     } catch(const CKM::Base64Decoder::Exception::Base &e) {
@@ -171,6 +190,11 @@ void CryptoLogic::encryptRow(const Password &password, DB::Row &row)
     }
 }
 
+int CryptoLogic::getSchemeVersion(int encryptionScheme)
+{
+    return encryptionScheme >> ENCR_ORDER_OFFSET;
+}
+
 void CryptoLogic::decryptRow(const Password &password, DB::Row &row)
 {
     try {
@@ -184,13 +208,19 @@ void CryptoLogic::decryptRow(const Password &password, DB::Row &row)
 
         if ((row.encryptionScheme & ENCR_PASSWORD) && password.empty()) {
             ThrowErr(Exc::AuthenticationFailed,
-              "DB row is password protected, but given password is "
-              "empty.");
+                     "DB row is password protected, but given password is empty.");
+        }
+
+        if(!(row.encryptionScheme & ENCR_PASSWORD) && !password.empty()) {
+            ThrowErr(Exc::AuthenticationFailed,
+                     "DB row is not password protected, but given password is not empty.");
         }
 
         if ((row.encryptionScheme & ENCR_APPKEY) && !haveKey(row.ownerLabel)) {
-            ThrowErr(Exc::AuthenticationFailed, "Missing application key for ",
-              row.ownerLabel, " label.");
+            ThrowErr(Exc::AuthenticationFailed,
+                     "Missing application key for ",
+                     row.ownerLabel,
+                     " label.");
         }
 
         decBase64(crow.iv);
@@ -198,16 +228,22 @@ void CryptoLogic::decryptRow(const Password &password, DB::Row &row)
             decBase64(crow.data);
         }
 
-        if (crow.encryptionScheme & ENCR_PASSWORD) {
-            key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE);
-            crow.data = Crypto::SW::Internals::decryptDataAesCbc(key, crow.data, crow.iv);
+        if((crow.encryptionScheme >> ENCR_ORDER_OFFSET) == ENCR_ORDER_V2) {
+            if (crow.encryptionScheme & ENCR_APPKEY) {
+                key = m_keyMap[crow.ownerLabel];
+                crow.data = Crypto::SW::Internals::decryptDataAesGcm(key, crow.data, crow.iv, crow.tag);
+            }
+        } else {
+            if (crow.encryptionScheme & ENCR_PASSWORD) {
+                key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE);
+                crow.data = Crypto::SW::Internals::decryptDataAes(AlgoType::AES_CBC, key, crow.data, crow.iv);
+            }
+
+            if (crow.encryptionScheme & ENCR_APPKEY) {
+                key = m_keyMap[crow.ownerLabel];
+                crow.data = Crypto::SW::Internals::decryptDataAesGcm(key, crow.data, crow.iv, crow.tag);
+            }
         }
-
-        if (crow.encryptionScheme & ENCR_APPKEY) {
-            key = m_keyMap[crow.ownerLabel];
-            crow.data = Crypto::SW::Internals::decryptDataAesGcm(key, crow.data, crow.iv, crow.tag);
-        }
-
         if (static_cast<int>(crow.data.size()) < crow.dataSize) {
             ThrowErr(Exc::AuthenticationFailed, "Decrypted row size mismatch");
         }
@@ -216,7 +252,7 @@ void CryptoLogic::decryptRow(const Password &password, DB::Row &row)
             crow.data.resize(crow.dataSize);
         }
 
-        row = crow;
+        row = std::move(crow);
     } catch(const CKM::Base64Encoder::Exception::Base &e) {
         ThrowErr(Exc::InternalError, e.GetMessage());
     } catch(const CKM::Base64Decoder::Exception::Base &e) {