]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dcrypt: Add padding parameter for RSA encrypt/decrypt
authorAki Tuomi <aki.tuomi@dovecot.fi>
Mon, 23 Jan 2017 15:40:01 +0000 (17:40 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Mon, 23 Sep 2019 05:47:52 +0000 (08:47 +0300)
src/lib-dcrypt/dcrypt-openssl.c
src/lib-dcrypt/dcrypt-private.h
src/lib-dcrypt/dcrypt.c
src/lib-dcrypt/dcrypt.h
src/lib-dcrypt/istream-decrypt.c
src/lib-dcrypt/ostream-encrypt.c

index f2b5dce4d7b2e8664bd00bc99f5422bbcf8430cf..d1ce9a6c41bd83721b9c408ca5dc6d10405bd6b2 100644 (file)
@@ -164,12 +164,15 @@ dcrypt_openssl_private_key_id_old(struct dcrypt_private_key *key,
 static void
 dcrypt_openssl_private_to_public_key(struct dcrypt_private_key *priv_key,
                                     struct dcrypt_public_key **pub_key_r);
-static void dcrypt_openssl_unref_private_key(struct dcrypt_private_key **key);
-static void dcrypt_openssl_unref_public_key(struct dcrypt_public_key **key);
+static void
+dcrypt_openssl_unref_private_key(struct dcrypt_private_key **key);
+static void
+dcrypt_openssl_unref_public_key(struct dcrypt_public_key **key);
 static bool
 dcrypt_openssl_rsa_decrypt(struct dcrypt_private_key *key,
                           const unsigned char *data, size_t data_len,
-                          buffer_t *result, const char **error_r);
+                          buffer_t *result, enum dcrypt_padding padding,
+                          const char **error_r);
 static bool
 dcrypt_openssl_key_string_get_info(const char *key_data,
        enum dcrypt_key_format *format_r, enum dcrypt_key_version *version_r,
@@ -192,6 +195,30 @@ static bool dcrypt_openssl_error(const char **error_r)
        return FALSE;
 }
 
+static int
+dcrypt_openssl_padding_mode(enum dcrypt_padding padding,
+                           bool sig, const char **error_r)
+{
+       switch (padding) {
+       case DCRYPT_PADDING_DEFAULT:
+               if (sig) return RSA_PKCS1_PSS_PADDING;
+               else return RSA_PKCS1_OAEP_PADDING;
+       case DCRYPT_PADDING_RSA_PKCS1_OAEP:
+               return RSA_PKCS1_OAEP_PADDING;
+       case DCRYPT_PADDING_RSA_PKCS1_PSS:
+               return RSA_PKCS1_PSS_PADDING;
+       case DCRYPT_PADDING_RSA_PKCS1:
+               return RSA_PKCS1_PADDING;
+       case DCRYPT_PADDING_RSA_NO:
+               return RSA_NO_PADDING;
+       default:
+               if (*error_r != NULL)
+                       *error_r = "Unsupported padding mode";
+               return -1;
+       }
+       i_unreached();
+}
+
 static bool dcrypt_openssl_initialize(const struct dcrypt_settings *set,
                                      const char **error_r)
 {
@@ -1283,7 +1310,7 @@ dcrypt_openssl_load_private_key_dovecot_v2(struct dcrypt_private_key **key_r,
                if (EVP_PKEY_base_id((EVP_PKEY*)dec_key) == EVP_PKEY_RSA) {
                        if (!dcrypt_openssl_rsa_decrypt(dec_key,
                                peer_key->data, peer_key->used, secret,
-                               error_r))
+                               DCRYPT_PADDING_RSA_PKCS1_OAEP, error_r))
                                return FALSE;
                } else {
                        /* perform ECDH */
@@ -2171,6 +2198,7 @@ dcrypt_openssl_encrypt_private_key_dovecot(buffer_t *key, int enctype,
                        buffer_set_used_size(secret, used+16);
                        if (!dcrypt_rsa_encrypt(enc_key, secret->data,
                                                secret->used, peer_key,
+                                               DCRYPT_PADDING_RSA_PKCS1_OAEP,
                                                error_r)) {
                                return FALSE;
                        }
@@ -2859,17 +2887,20 @@ static void dcrypt_openssl_unref_keypair(struct dcrypt_keypair *keypair)
 static bool
 dcrypt_openssl_rsa_encrypt(struct dcrypt_public_key *key,
                           const unsigned char *data, size_t data_len,
-                          buffer_t *result, const char **error_r)
+                          buffer_t *result, enum dcrypt_padding padding,
+                          const char **error_r)
 {
-       int ec;
        i_assert(key != NULL && key->key != NULL);
+       int ec, pad = dcrypt_openssl_padding_mode(padding, FALSE, error_r);
+       if (pad == -1)
+               return FALSE;
        EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key->key, NULL);
        size_t outl = EVP_PKEY_size(key->key);
        unsigned char buf[outl];
 
        if (ctx == NULL ||
            EVP_PKEY_encrypt_init(ctx) < 1 ||
-           EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
+           EVP_PKEY_CTX_set_rsa_padding(ctx, pad) < 1 ||
            EVP_PKEY_encrypt(ctx, buf, &outl, data, data_len) < 1) {
                dcrypt_openssl_error(error_r);
                ec = -1;
@@ -2886,17 +2917,20 @@ dcrypt_openssl_rsa_encrypt(struct dcrypt_public_key *key,
 static bool
 dcrypt_openssl_rsa_decrypt(struct dcrypt_private_key *key,
                           const unsigned char *data, size_t data_len,
-                          buffer_t *result, const char **error_r)
+                          buffer_t *result, enum dcrypt_padding padding,
+                          const char **error_r)
 {
-       int ec;
        i_assert(key != NULL && key->key != NULL);
+       int ec, pad = dcrypt_openssl_padding_mode(padding, FALSE, error_r);
+       if (pad == -1)
+               return FALSE;
        EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key->key, NULL);
        size_t outl = EVP_PKEY_size(key->key);
        unsigned char buf[outl];
 
        if (ctx == NULL ||
            EVP_PKEY_decrypt_init(ctx) < 1 ||
-           EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 ||
+           EVP_PKEY_CTX_set_rsa_padding(ctx, pad) < 1 ||
            EVP_PKEY_decrypt(ctx, buf, &outl, data, data_len) < 1) {
                dcrypt_openssl_error(error_r);
                ec = -1;
index bf3a5f192d2030e952ba9a4a2c2dd2b7abccbfc6..96fa8d3c961ec564e7db512638962cb87e4004a7 100644 (file)
@@ -129,10 +129,12 @@ struct dcrypt_vfs {
 
        bool (*rsa_encrypt)(struct dcrypt_public_key *key,
                            const unsigned char *data, size_t data_len,
-                           buffer_t *result, const char **error_r);
+                           buffer_t *result, enum dcrypt_padding padding,
+                           const char **error_r);
        bool (*rsa_decrypt)(struct dcrypt_private_key *key,
                            const unsigned char *data, size_t data_len,
-                           buffer_t *result, const char **error_r);
+                           buffer_t *result, enum dcrypt_padding padding,
+                           const char **error_r);
 
        const char *(*oid2name)(const unsigned char *oid,
                                size_t oid_len, const char **error_r);
index 0d8dbf53ef6a65f488cf2640e404fd7ac4848802..6b2abc9b0c3c58be0a729c4965c3e69285a4148f 100644 (file)
@@ -408,18 +408,22 @@ void dcrypt_key_unref_private(struct dcrypt_private_key **key)
 
 bool dcrypt_rsa_encrypt(struct dcrypt_public_key *key,
                        const unsigned char *data, size_t data_len,
-                       buffer_t *result, const char **error_r)
+                       buffer_t *result, enum dcrypt_padding padding,
+                       const char **error_r)
 {
        i_assert(dcrypt_vfs != NULL);
-       return dcrypt_vfs->rsa_encrypt(key, data, data_len, result, error_r);
+       return dcrypt_vfs->rsa_encrypt(key, data, data_len, result,
+                                      padding, error_r);
 }
 
 bool dcrypt_rsa_decrypt(struct dcrypt_private_key *key,
                        const unsigned char *data, size_t data_len,
-                       buffer_t *result, const char **error_r)
+                       buffer_t *result, enum dcrypt_padding padding,
+                       const char **error_r)
 {
        i_assert(dcrypt_vfs != NULL);
-       return dcrypt_vfs->rsa_decrypt(key, data, data_len, result, error_r);
+       return dcrypt_vfs->rsa_decrypt(key, data, data_len, result,
+                                      padding, error_r);
 }
 
 const char *dcrypt_oid2name(const unsigned char *oid, size_t oid_len,
index dbb6bef9433dfb9c7820ccea3aa22277c031a9b9..ab22d9b4f3351d0629a525be51bc7811dac0d066 100644 (file)
@@ -376,10 +376,12 @@ void dcrypt_key_set_usage_private(struct dcrypt_private_key *key,
 /* RSA stuff */
 bool dcrypt_rsa_encrypt(struct dcrypt_public_key *key,
                        const unsigned char *data, size_t data_len,
-                       buffer_t *result, const char **error_r);
+                       buffer_t *result, enum dcrypt_padding padding,
+                       const char **error_r);
 bool dcrypt_rsa_decrypt(struct dcrypt_private_key *key,
                        const unsigned char *data, size_t data_len,
-                       buffer_t *result, const char **error_r);
+                       buffer_t *result, enum dcrypt_padding padding,
+                       const char **error_r);
 
 /* OID stuff */
 const char *dcrypt_oid2name(const unsigned char *oid, size_t oid_len,
index db0ea708eb4078a00ee7958760ac06629e9c3fd8..96fcc978321b8db4fd786dc995990499eb58c74d 100644 (file)
@@ -435,8 +435,9 @@ i_stream_decrypt_key(struct decrypt_istream *stream, const char *malg,
 
        /* decrypt the seed */
        if (ktype == DCRYPT_KEY_RSA) {
-               if (!dcrypt_rsa_decrypt(stream->priv_key, encrypted_key,
-                                       eklen, key, &error)) {
+               if (!dcrypt_rsa_decrypt(stream->priv_key, encrypted_key, eklen,
+                                       key, DCRYPT_PADDING_RSA_PKCS1_OAEP,
+                                       &error)) {
                        io_stream_set_error(&stream->istream.iostream,
                                            "key decryption error: %s", error);
                        return -1;
index 585e2a530a3a4178a78020f89cab2d7a9d443af8..3264725ebf5fd8b00ffcf082feeea0a04905cdc6 100644 (file)
@@ -277,8 +277,9 @@ o_stream_encrypt_key_for_pubkey_v2(struct encrypt_ostream *stream,
 
        if (ktype == DCRYPT_KEY_RSA) {
                /* encrypt key as R (as we don't need DH with RSA)*/
-               if (!dcrypt_rsa_encrypt(pubkey, key, key_len,
-                                       encrypted_key, &error)) {
+               if (!dcrypt_rsa_encrypt(pubkey, key, key_len, encrypted_key,
+                                       DCRYPT_PADDING_RSA_PKCS1_OAEP,
+                                       &error)) {
                        io_stream_set_error(&stream->ostream.iostream,
                                            "Cannot encrypt key data: %s",
                                            error);