]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
gcrypt: Support RSA OAEP SHA1 encryption/decryption
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 10 Nov 2021 20:04:00 +0000 (21:04 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 10 Nov 2021 20:06:10 +0000 (21:06 +0100)
src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c

index c37cd57e7f1eb35548714328401eb30c10544025..fc4d9467d72d8a7438ed3c83e047fd365c058249 100644 (file)
@@ -135,6 +135,7 @@ METHOD(plugin_t, get_features, int,
                PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1),
                PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5),
                PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_PKCS1),
+               PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA1),
                /* signature verification schemes */
 #if GCRYPT_VERSION_NUMBER >= 0x010700
                PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS),
@@ -147,6 +148,7 @@ METHOD(plugin_t, get_features, int,
                PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1),
                PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_MD5),
                PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_PKCS1),
+               PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA1),
                /* random numbers */
                PLUGIN_REGISTER(RNG, gcrypt_rng_create),
                        PLUGIN_PROVIDE(RNG, RNG_WEAK),
index 5bc0a72ec56c6d06fbe8a379fd59b0ee1e4c3aa3..5ef7daf61011ce790810df43c62cc544be756a88 100644 (file)
@@ -282,49 +282,53 @@ METHOD(private_key_t, decrypt, bool,
 {
        gcry_error_t err;
        gcry_sexp_t in, out;
-       chunk_t padded;
-       u_char *pos = NULL;;
+       chunk_t label = chunk_empty, decrypted;
+       u_char *sexp;
 
-       if (scheme != ENCRYPT_RSA_PKCS1)
+       switch (scheme)
        {
-               DBG1(DBG_LIB, "encryption scheme %N not supported",
-                        encryption_scheme_names, scheme);
-               return FALSE;
+               case ENCRYPT_RSA_PKCS1:
+                       sexp = "(enc-val(flags pkcs1)(rsa(a %b)))";
+                       break;
+               case ENCRYPT_RSA_OAEP_SHA1:
+                       sexp = "(enc-val(flags oaep)(rsa(a %b)))";
+                       break;
+               default:
+                       DBG1(DBG_LIB, "encryption scheme %N not supported",
+                                encryption_scheme_names, scheme);
+                       return FALSE;
        }
-       err = gcry_sexp_build(&in, NULL, "(enc-val(flags)(rsa(a %b)))",
-                                                 encrypted.len, encrypted.ptr);
+
+       if (scheme == ENCRYPT_RSA_OAEP_SHA1 && params != NULL)
+       {
+               label = *(chunk_t *)params;
+               if (label.len > 0)
+               {
+                       DBG1(DBG_LIB, "RSA OAEP decryption with a label not supported");
+                       return FALSE;
+               }
+       }
+
+       err = gcry_sexp_build(&in, NULL, sexp, encrypted.len, encrypted.ptr);
        if (err)
        {
                DBG1(DBG_LIB, "building decryption S-expression failed: %s",
                         gpg_strerror(err));
                return FALSE;
        }
+
        err = gcry_pk_decrypt(&out, in, this->key);
        gcry_sexp_release(in);
        if (err)
        {
-               DBG1(DBG_LIB, "decrypting pkcs1 data failed: %s", gpg_strerror(err));
+               DBG1(DBG_LIB, "RSA decryption failed: %s", gpg_strerror(err));
                return FALSE;
        }
-       padded.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &padded.len);
-       /* result is padded, but gcrypt strips leading zero:
-        *  00 | 02 | RANDOM | 00 | DATA */
-       if (padded.ptr && padded.len > 2 && padded.ptr[0] == 0x02)
-       {
-               pos = memchr(padded.ptr, 0x00, padded.len - 1);
-               if (pos)
-               {
-                       pos++;
-                       *plain = chunk_clone(chunk_create(
-                                                                               pos, padded.len - (pos - padded.ptr)));
-               }
-       }
+
+       decrypted.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &decrypted.len);
+       *plain = chunk_clone(decrypted);
        gcry_sexp_release(out);
-       if (!pos)
-       {
-               DBG1(DBG_LIB, "decrypted data has invalid pkcs1 padding");
-               return FALSE;
-       }
+
        return TRUE;
 }
 
index 694a969f80e099cf5132e1f922a5c019a96c6c11..2200a21187bfc26f61f17b19f76eb15220c37767 100644 (file)
@@ -239,36 +239,55 @@ METHOD(public_key_t, encrypt_, bool,
        private_gcrypt_rsa_public_key_t *this, encryption_scheme_t scheme,
        void *params, chunk_t plain, chunk_t *encrypted)
 {
-       gcry_sexp_t in, out;
        gcry_error_t err;
+       gcry_sexp_t in, out;
+       chunk_t label = chunk_empty;
+       u_char *sexp;
 
-       if (scheme != ENCRYPT_RSA_PKCS1)
+       switch (scheme)
        {
-               DBG1(DBG_LIB, "encryption scheme %N not supported",
-                        encryption_scheme_names, scheme);
-               return FALSE;
+               case ENCRYPT_RSA_PKCS1:
+                       sexp = "(data(flags pkcs1)(value %b))";
+                       break;
+               case ENCRYPT_RSA_OAEP_SHA1:
+                       sexp = "(data(flags oaep)(value %b))";
+                       break;
+               default:
+                       DBG1(DBG_LIB, "encryption scheme %N not supported",
+                                encryption_scheme_names, scheme);
+                       return FALSE;
        }
-       /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption:
-        * 00 | 02 | RANDOM | 00 | DATA */
-       err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(value %b))",
-                                                 plain.len, plain.ptr);
+
+       if (scheme == ENCRYPT_RSA_OAEP_SHA1 && params != NULL)
+       {
+               label = *(chunk_t *)params;
+               if (label.len > 0)
+               {
+                       DBG1(DBG_LIB, "RSA OAEP encryption with a label not supported");
+                       return FALSE;
+               }
+       }
+
+       err = gcry_sexp_build(&in, NULL, sexp, plain.len, plain.ptr);
        if (err)
        {
                DBG1(DBG_LIB, "building encryption S-expression failed: %s",
                         gpg_strerror(err));
                return FALSE;
        }
+
        err = gcry_pk_encrypt(&out, in, this->key);
        gcry_sexp_release(in);
        if (err)
        {
-               DBG1(DBG_LIB, "encrypting data using pkcs1 failed: %s",
-                        gpg_strerror(err));
+               DBG1(DBG_LIB, "RSA encryption failed: %s", gpg_strerror(err));
                return FALSE;
        }
+
        *encrypted = gcrypt_rsa_find_token(out, "a", this->key);
        gcry_sexp_release(out);
-       return !!encrypted->len;
+
+       return encrypted->len > 0;
 }
 
 METHOD(public_key_t, get_keysize, int,