Add RSA OAEP support 46/43046/4
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 7 Jul 2015 10:10:50 +0000 (12:10 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 28 Jul 2015 09:04:59 +0000 (02:04 -0700)
[Feature] Encryption service development
[Solution] Add support for RSA OAEP encryption/decryption

[Verification] Run ckm-tests --group=CKM_ENCRYPTION_DECRYPTION

Change-Id: Ieb78fcb65fbd6e2042c2b7effe1ef7b66429fcbd

src/manager/crypto/generic-backend/algo-validation.h
src/manager/crypto/sw-backend/internals.cpp
src/manager/crypto/sw-backend/internals.h
src/manager/crypto/sw-backend/key.cpp
src/manager/crypto/sw-backend/key.h

index c8abc72..69dd95d 100644 (file)
@@ -85,6 +85,12 @@ struct Type {
     };
 };
 
+template <typename T>
+struct Unsupported {
+    static bool Check(const T&) { return false; }
+    static void Why(std::ostringstream& os) { os << "is not supported"; }
+};
+
 
 ////////// Getters //////////////
 
@@ -93,12 +99,19 @@ template <typename T>
 struct DefaultGetter {
     static T Get(const T& value) { return value; }
     static void What(std::ostringstream& os) { os << "value"; }
+    static void Print(std::ostringstream& os, const T& value) { os << static_cast<int>(value); }
 };
 
+template <>
+void DefaultGetter<RawBuffer>::Print(std::ostringstream& os, const RawBuffer& buffer) {
+    os << "[" << buffer.size() << "B buffer]";
+}
+
 // returns buffer param size
 struct BufferSizeGetter {
     static size_t Get(const RawBuffer& buffer) { return buffer.size(); }
     static void What(std::ostringstream& os) { os << "buffer size"; }
+    static void Print(std::ostringstream& os, const RawBuffer& buffer) { os << buffer.size(); }
 };
 
 
@@ -126,6 +139,13 @@ typedef std::vector<ParamCheckBasePtr> ValidatorVector;
 template <typename ...Args>
 struct VBuilder;
 
+template <>
+struct VBuilder<> {
+static ValidatorVector Build() {
+        return ValidatorVector();
+    }
+};
+
 template <typename First>
 struct VBuilder<First> {
 static ValidatorVector Build() {
@@ -187,8 +207,9 @@ struct ParamCheck : public ParamCheckBase {
         if(!Validator::Check(Getter::Get(value))) {
             os << "The ";
             Getter::What(os);
-            os << " of param '" << static_cast<int>(Name) << "'=" <<
-                  static_cast<int>(Getter::Get(value)) << " ";
+            os << " of param '" << static_cast<int>(Name) << "'=";
+            Getter::Print(os, value);
+            os << " ";
             Validator::Why(os);
             ErrorHandler::Handle(os.str());
         }
index df9fbb7..3875c2b 100644 (file)
@@ -96,8 +96,12 @@ typedef ParamCheck<ParamName::ALGO_TYPE,
                    Type<AlgoType>::Equals<AlgoType::AES_CTR,
                                           AlgoType::AES_CBC,
                                           AlgoType::AES_GCM,
-                                          AlgoType::AES_CFB,
-                                          AlgoType::RSA_OAEP>> IsEncryption;
+                                          AlgoType::AES_CFB>> IsSymEncryption;
+
+typedef ParamCheck<ParamName::ALGO_TYPE,
+                   AlgoType,
+                   true,
+                   Type<AlgoType>::Equals<AlgoType::RSA_OAEP>> IsAsymEncryption;
 
 typedef ParamCheck<ParamName::ED_IV,
                    RawBuffer,
@@ -113,14 +117,18 @@ typedef ParamCheck<ParamName::ED_CTR_LEN,
 typedef ParamCheck<ParamName::ED_IV,
                    RawBuffer,
                    true,
-                   DefaultValidator<size_t>,
-                   BufferSizeGetter> GcmIvCheck;
+                   DefaultValidator<RawBuffer>> GcmIvCheck;
 
 typedef ParamCheck<ParamName::ED_TAG_LEN,
                    int,
                    false,
                    Type<int>::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck;
 
+typedef ParamCheck<ParamName::ED_LABEL,
+                   RawBuffer,
+                   false,
+                   Unsupported<RawBuffer>> RsaLabelCheck;
+
 // sign / verify
 typedef ParamCheck<ParamName::ALGO_TYPE,
                    AlgoType,
@@ -195,6 +203,7 @@ ValidatorMap initValidators() {
     validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
     validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
     validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
+    validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck>::Build());
     return validators;
 };
 ValidatorMap g_validators = initValidators();
@@ -207,8 +216,11 @@ void validateParams(const CryptoAlgorithm& ca)
     tc.Check(ca);
 
     AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
-    for(const auto& validator : g_validators.at(at)) {
-        validator->Check(ca);
+    try {
+        for(const auto& validator : g_validators.at(at))
+            validator->Check(ca);
+    } catch(const std::out_of_range&) {
+        ThrowErr(Exc::Crypto::InputParam, "Unsupported algorithm ", static_cast<int>(at));
     }
 }
 
@@ -279,6 +291,39 @@ InitCipherFn selectCipher(AlgoType type, size_t key_len = 32, bool encryption =
     }
 }
 
+
+RawBuffer asymmetricHelper(int (*cryptoFn)(int, const unsigned char*, unsigned char*, RSA*, int),
+                           const std::string logPrefix,
+                           const EvpShPtr &pkey,
+                           const CryptoAlgorithm &alg,
+                           const RawBuffer &data)
+{
+    validateParams<IsAsymEncryption>(alg);
+
+    RSA* rsa = EVP_PKEY_get1_RSA(pkey.get());
+    if (!rsa)
+        ThrowErr(Exc::Crypto::InputParam, logPrefix, "invalid key");
+
+    /*
+     * RSA_padding_add_PKCS1_OAEP supports custom label but RSA_public_encrypt calls it with NULL
+     * value so for now label is not supported. Alternative is to rewrite the openssl implementation
+     * to support it: openssl-fips/crypto/rsa/rsa_eay.c
+     */
+    RawBuffer output;
+    output.resize(RSA_size(rsa));
+    int ret = cryptoFn(data.size(),
+                   data.data(),
+                   output.data(),
+                   rsa,
+                   RSA_PKCS1_OAEP_PADDING);
+    RSA_free(rsa);
+    if (ret < 0)
+        ThrowErr(Exc::Crypto::InternalError, logPrefix, "failed");
+
+    output.resize(ret);
+    return output;
+}
+
 } // anonymous namespace
 
 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
@@ -625,7 +670,7 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
                            const CryptoAlgorithm &alg,
                            const RawBuffer &data)
 {
-    validateParams<IsEncryption>(alg);
+    validateParams<IsSymEncryption>(alg);
     AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
     switch(keyType)
@@ -649,15 +694,14 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
         default:
             break;
     }
-    ThrowErr(Exc::Crypto::OperationNotSupported,
-        "symmetric enc error: algorithm not recognized");
+    ThrowErr(Exc::Crypto::OperationNotSupported, "symmetric enc: algorithm not recognized");
 }
 
 RawBuffer symmetricDecrypt(const RawBuffer &key,
                            const CryptoAlgorithm &alg,
                            const RawBuffer &data)
 {
-    validateParams<IsEncryption>(alg);
+    validateParams<IsSymEncryption>(alg);
     AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
     switch(keyType)
@@ -681,7 +725,21 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
         default:
             break;
     }
-    ThrowErr(Exc::Crypto::InputParam, "symmetric dec error: algorithm not recognized");
+    ThrowErr(Exc::Crypto::InputParam, "symmetric dec: algorithm not recognized");
+}
+
+RawBuffer asymmetricEncrypt(const EvpShPtr &pkey,
+                            const CryptoAlgorithm &alg,
+                            const RawBuffer &data)
+{
+    return asymmetricHelper(RSA_public_encrypt, "Asymmetric encryption: ", pkey, alg, data);
+}
+
+RawBuffer asymmetricDecrypt(const EvpShPtr &pkey,
+                            const CryptoAlgorithm &alg,
+                            const RawBuffer &data)
+{
+    return asymmetricHelper(RSA_private_decrypt, "Asymmetric decryption: ", pkey, alg, data);
 }
 
 RawBuffer sign(EVP_PKEY *pkey,
index 4d810d5..c71d106 100644 (file)
@@ -25,6 +25,7 @@
 #include <ckm/ckm-type.h>
 #include <openssl/evp.h>
 #include <token.h>
+#include <sw-backend/key.h>
 
 #define EVP_SUCCESS 1  // DO NOTCHANGE THIS VALUE
 #define EVP_FAIL    0  // DO NOTCHANGE THIS VALUE
@@ -53,6 +54,12 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
 RawBuffer symmetricDecrypt(const RawBuffer &key,
                            const CryptoAlgorithm &alg,
                            const RawBuffer &cipher);
+RawBuffer asymmetricEncrypt(const EvpShPtr &key,
+                            const CryptoAlgorithm &alg,
+                            const RawBuffer &data);
+RawBuffer asymmetricDecrypt(const EvpShPtr &key,
+                            const CryptoAlgorithm &alg,
+                            const RawBuffer &data);
 
 std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(const RawBuffer &key,
     const RawBuffer &data,
index 7ff0ebb..b1e57ff 100644 (file)
@@ -108,6 +108,16 @@ int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message, const Raw
     return Internals::verify(evp, algWithType, message, sign);
 }
 
+RawBuffer AKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
+{
+    return Internals::asymmetricEncrypt(getEvpShPtr(), alg, data);
+}
+
+RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
+{
+    return Internals::asymmetricDecrypt(getEvpShPtr(), alg, data);
+}
+
 EvpShPtr AKey::getEvpShPtr() {
     if (m_evp)
         return m_evp;
index df331ec..d5b7bfe 100644 (file)
@@ -56,6 +56,8 @@ public:
     {}
     virtual RawBuffer sign(const CryptoAlgorithm &alg, const RawBuffer &message);
     virtual int verify(const CryptoAlgorithm &alg, const RawBuffer &message, const RawBuffer &sign);
+    virtual RawBuffer encrypt(const CryptoAlgorithm &, const RawBuffer &);
+    virtual RawBuffer decrypt(const CryptoAlgorithm &, const RawBuffer &);
     virtual RawBuffer getBinary() const;
     virtual ~AKey(){}
 protected: