diff --git a/doc/guides/cryptodevs/features/qat.ini b/doc/guides/cryptodevs/features/qat.ini
index 0832e59..afbc71a 100644
--- a/doc/guides/cryptodevs/features/qat.ini
+++ b/doc/guides/cryptodevs/features/qat.ini
@@ -70,3 +70,4 @@ AES CCM (256) = Y
 [Asymmetric]
 Modular Exponentiation  = Y
 Modular Inversion		= Y
+RSA						= Y
diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst
index 2e79d17..a8c4efd 100644
--- a/doc/guides/rel_notes/release_19_11.rst
+++ b/doc/guides/rel_notes/release_19_11.rst
@@ -59,6 +59,7 @@ New Features
 * **Updated the Intel QuickAssist Technology (QAT) asymmetric crypto PMD.**
 
   Added support for session-less operations.
+  Added support for RSA algorithm with pair (n, d) private key representation.
 
 Removed Items
 -------------
diff --git a/drivers/common/qat/qat_adf/qat_pke_functionality_arrays.h b/drivers/common/qat/qat_adf/qat_pke_functionality_arrays.h
index 8adf209..4f857b9 100644
--- a/drivers/common/qat/qat_adf/qat_pke_functionality_arrays.h
+++ b/drivers/common/qat/qat_adf/qat_pke_functionality_arrays.h
@@ -49,4 +49,22 @@ static const uint32_t MOD_INV_IDS_EVEN[][2] = {
 		{ 4096, MATHS_MODINV_EVEN_L4096 },
 };
 
+static const uint32_t RSA_MODEXP_ENC_IDS[][2] = {
+		{ 512,	PKE_RSA_EP_512 },
+		{ 1024,	PKE_RSA_EP_1024 },
+		{ 1536,	PKE_RSA_EP_1536 },
+		{ 2048,	PKE_RSA_EP_2048 },
+		{ 3072,	PKE_RSA_EP_3072 },
+		{ 4096,	PKE_RSA_EP_4096 },
+};
+
+static const uint32_t RSA_MODEXP_DEC_IDS[][2] = {
+		{ 512,	PKE_RSA_DP1_512 },
+		{ 1024,	PKE_RSA_DP1_1024 },
+		{ 1536,	PKE_RSA_DP1_1536 },
+		{ 2048,	PKE_RSA_DP1_2048 },
+		{ 3072,	PKE_RSA_DP1_3072 },
+		{ 4096,	PKE_RSA_DP1_4096 },
+};
+
 #endif
diff --git a/drivers/crypto/qat/qat_asym.c b/drivers/crypto/qat/qat_asym.c
index bf5d22d..8985270 100644
--- a/drivers/crypto/qat/qat_asym.c
+++ b/drivers/crypto/qat/qat_asym.c
@@ -228,6 +228,170 @@ qat_asym_fill_arrays(struct rte_crypto_asym_op *asym_op,
 				cookie->input_array[1],
 				alg_size_in_bytes);
 #endif
+	} else if (xform->xform_type == RTE_CRYPTO_ASYM_XFORM_RSA) {
+		err = qat_asym_check_nonzero(xform->rsa.n);
+		if (err) {
+			QAT_LOG(ERR, "Empty modulus in RSA"
+					" inverse, aborting this operation");
+			return err;
+		}
+
+		alg_size_in_bytes = xform->rsa.n.length;
+		alg_size = alg_size_in_bytes << 3;
+
+		qat_req->input_param_count =
+				QAT_ASYM_RSA_NUM_IN_PARAMS;
+		qat_req->output_param_count =
+				QAT_ASYM_RSA_NUM_OUT_PARAMS;
+
+		if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT ||
+				asym_op->rsa.op_type ==
+						RTE_CRYPTO_ASYM_OP_VERIFY) {
+
+			if (qat_asym_get_sz_and_func_id(RSA_MODEXP_ENC_IDS,
+					sizeof(RSA_MODEXP_ENC_IDS)/
+					sizeof(*RSA_MODEXP_ENC_IDS),
+					&alg_size, &func_id)) {
+				err = QAT_ASYM_ERROR_INVALID_PARAM;
+				QAT_LOG(ERR,
+					"Not supported RSA parameter size (key)");
+				return err;
+			}
+			alg_size_in_bytes = alg_size >> 3;
+			if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
+				switch (asym_op->rsa.pad) {
+				case RTE_CRYPTO_RSA_PADDING_NONE:
+					rte_memcpy(cookie->input_array[0] +
+						alg_size_in_bytes -
+						asym_op->rsa.message.length
+						, asym_op->rsa.message.data,
+						asym_op->rsa.message.length);
+					break;
+				default:
+					err = QAT_ASYM_ERROR_INVALID_PARAM;
+					QAT_LOG(ERR,
+						"Invalid RSA padding (Encryption)");
+					return err;
+				}
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+				QAT_DP_HEXDUMP_LOG(DEBUG, "Message",
+						cookie->input_array[0],
+						alg_size_in_bytes);
+#endif
+			} else {
+				switch (asym_op->rsa.pad) {
+				case RTE_CRYPTO_RSA_PADDING_NONE:
+					rte_memcpy(cookie->input_array[0],
+						asym_op->rsa.sign.data,
+						asym_op->rsa.sign.length);
+					break;
+				default:
+					err = QAT_ASYM_ERROR_INVALID_PARAM;
+					QAT_LOG(ERR,
+						"Invalid RSA padding (Verify)");
+					return err;
+				}
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+				QAT_DP_HEXDUMP_LOG(DEBUG, "Signature",
+						cookie->input_array[0],
+						alg_size_in_bytes);
+#endif
+
+			}
+			rte_memcpy(cookie->input_array[1] +
+					alg_size_in_bytes -
+					xform->rsa.e.length
+					, xform->rsa.e.data,
+					xform->rsa.e.length);
+			rte_memcpy(cookie->input_array[2] +
+					alg_size_in_bytes -
+					xform->rsa.n.length,
+					xform->rsa.n.data,
+					xform->rsa.n.length);
+
+			cookie->alg_size = alg_size;
+			qat_req->pke_hdr.cd_pars.func_id = func_id;
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+			QAT_DP_HEXDUMP_LOG(DEBUG, "Public Key",
+					cookie->input_array[1], alg_size_in_bytes);
+			QAT_DP_HEXDUMP_LOG(DEBUG, "Modulus",
+					cookie->input_array[2], alg_size_in_bytes);
+#endif
+		} else {
+			if (asym_op->rsa.op_type ==
+					RTE_CRYPTO_ASYM_OP_DECRYPT) {
+				switch (asym_op->rsa.pad) {
+				case RTE_CRYPTO_RSA_PADDING_NONE:
+					rte_memcpy(cookie->input_array[0]
+						+ alg_size_in_bytes -
+						asym_op->rsa.cipher.length,
+						asym_op->rsa.cipher.data,
+						asym_op->rsa.cipher.length);
+					break;
+				default:
+					QAT_LOG(ERR,
+						"Invalid padding of RSA (Decrypt)");
+					return QAT_ASYM_ERROR_INVALID_PARAM;
+				}
+
+			} else if (asym_op->rsa.op_type ==
+					RTE_CRYPTO_ASYM_OP_SIGN) {
+				switch (asym_op->rsa.pad) {
+				case RTE_CRYPTO_RSA_PADDING_NONE:
+					rte_memcpy(cookie->input_array[0]
+						+ alg_size_in_bytes -
+						asym_op->rsa.message.length,
+						asym_op->rsa.message.data,
+						asym_op->rsa.message.length);
+					break;
+				default:
+					QAT_LOG(ERR,
+						"Invalid padding of RSA (Signature)");
+					return QAT_ASYM_ERROR_INVALID_PARAM;
+				}
+			}
+
+			if (xform->rsa.key_type == RTE_RSA_KET_TYPE_QT) {
+				QAT_LOG(ERR, "RSA CRT not implemented");
+				return QAT_ASYM_ERROR_INVALID_PARAM;
+			} else if (xform->rsa.key_type ==
+					RTE_RSA_KEY_TYPE_EXP) {
+				if (qat_asym_get_sz_and_func_id(
+						RSA_MODEXP_DEC_IDS,
+						sizeof(RSA_MODEXP_DEC_IDS)/
+						sizeof(*RSA_MODEXP_DEC_IDS),
+						&alg_size, &func_id)) {
+					return QAT_ASYM_ERROR_INVALID_PARAM;
+				}
+				alg_size_in_bytes = alg_size >> 3;
+				rte_memcpy(cookie->input_array[1] +
+						alg_size_in_bytes -
+						xform->rsa.d.length,
+						xform->rsa.d.data,
+						xform->rsa.d.length);
+				rte_memcpy(cookie->input_array[2] +
+						alg_size_in_bytes -
+						xform->rsa.n.length,
+						xform->rsa.n.data,
+						xform->rsa.n.length);
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+			QAT_DP_HEXDUMP_LOG(DEBUG, "C", cookie->input_array[0],
+					alg_size_in_bytes);
+			QAT_DP_HEXDUMP_LOG(DEBUG, "d", cookie->input_array[1],
+					alg_size_in_bytes);
+			QAT_DP_HEXDUMP_LOG(DEBUG, "n", cookie->input_array[2],
+					alg_size_in_bytes);
+#endif
+
+				cookie->alg_size = alg_size;
+				qat_req->pke_hdr.cd_pars.func_id = func_id;
+			} else {
+				QAT_LOG(ERR, "Invalid RSA key type");
+				return QAT_ASYM_ERROR_INVALID_PARAM;
+			}
+		}
 	}
 	return 0;
 }
@@ -252,8 +416,10 @@ qat_asym_build_request(void *in_op,
 		ctx = (struct qat_asym_session *)
 			get_asym_session_private_data(
 			op->asym->session, cryptodev_qat_asym_driver_id);
-		rte_mov64((uint8_t *)qat_req, (const uint8_t *)&(ctx->req_tmpl));
-		err = qat_asym_fill_arrays(asym_op, qat_req, cookie, ctx->xform);
+		rte_mov64((uint8_t *)qat_req,
+				(const uint8_t *)&(ctx->req_tmpl));
+		err = qat_asym_fill_arrays(asym_op, qat_req,
+				cookie, ctx->xform);
 		if (err) {
 			op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 			goto error;
@@ -347,6 +513,81 @@ static void qat_asym_collect_response(struct rte_crypto_op *rx_op,
 					alg_size_in_bytes);
 #endif
 		}
+	} else if (xform->xform_type == RTE_CRYPTO_ASYM_XFORM_RSA) {
+		uint8_t *rsa_result = asym_op->rsa.cipher.data;
+
+		alg_size = cookie->alg_size;
+		alg_size_in_bytes = alg_size >> 3;
+		if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT ||
+				asym_op->rsa.op_type ==
+					RTE_CRYPTO_ASYM_OP_VERIFY) {
+			if (asym_op->rsa.op_type ==
+					RTE_CRYPTO_ASYM_OP_ENCRYPT) {
+				rte_memcpy(rsa_result,
+						cookie->output_array[0],
+						xform->rsa.n.length);
+				rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+				QAT_DP_HEXDUMP_LOG(DEBUG, "Encrypted data",
+						cookie->output_array[0],
+						alg_size_in_bytes);
+				asym_op->rsa.cipher.length = alg_size_in_bytes;
+#endif
+			} else if (asym_op->rsa.op_type ==
+					RTE_CRYPTO_ASYM_OP_VERIFY) {
+				rsa_result = asym_op->rsa.message.data;
+				switch (asym_op->rsa.pad) {
+				case RTE_CRYPTO_RSA_PADDING_NONE:
+					rte_memcpy(rsa_result,
+							cookie->output_array[0],
+							xform->rsa.n.length);
+					rx_op->status =
+						RTE_CRYPTO_OP_STATUS_SUCCESS;
+					break;
+				default:
+					QAT_LOG(ERR, "Error during setting "
+							"Padding not supported");
+					rx_op->status =
+						RTE_CRYPTO_OP_STATUS_ERROR;
+					break;
+				}
+			}
+		} else {
+			rsa_result = asym_op->rsa.message.data;
+			if (asym_op->rsa.op_type ==
+					RTE_CRYPTO_ASYM_OP_DECRYPT) {
+				switch (asym_op->rsa.pad) {
+				case RTE_CRYPTO_RSA_PADDING_NONE:
+					rte_memcpy(rsa_result,
+						cookie->output_array[0],
+						xform->rsa.n.length
+						);
+					break;
+				default:
+					QAT_LOG(ERR, "Error during setting "
+							"Padding not supported");
+					rx_op->status =
+						RTE_CRYPTO_OP_STATUS_ERROR;
+					break;
+				}
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+				QAT_DP_HEXDUMP_LOG(DEBUG, "RSA Decrypted Message",
+						rsa_result, alg_size_in_bytes);
+#endif
+			} else if (asym_op->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
+				rsa_result = asym_op->rsa.sign.data;
+				rte_memcpy(rsa_result,
+						cookie->output_array[0],
+						xform->rsa.n.length
+						);
+				rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+				QAT_DP_HEXDUMP_LOG(DEBUG, "RSA Signature",
+						cookie->output_array[0],
+						alg_size_in_bytes);
+#endif
+			}
+		}
 	}
 	qat_clear_arrays_by_alg(cookie, xform->xform_type, alg_size_in_bytes,
 			alg_size_in_bytes);
@@ -396,7 +637,7 @@ qat_asym_process_response(void **op, uint8_t *resp,
 
 	if (rx_op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
 		ctx = (struct qat_asym_session *)get_asym_session_private_data(
-				rx_op->asym->session, cryptodev_qat_asym_driver_id);
+			rx_op->asym->session, cryptodev_qat_asym_driver_id);
 		qat_asym_collect_response(rx_op, cookie, ctx->xform);
 	} else if (rx_op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
 		qat_asym_collect_response(rx_op, cookie, rx_op->asym->xform);
@@ -438,6 +679,12 @@ qat_asym_session_configure(struct rte_cryptodev *dev,
 			err = -EINVAL;
 			goto error;
 		}
+	} else if (xform->xform_type == RTE_CRYPTO_ASYM_XFORM_RSA) {
+		if (xform->rsa.n.length == 0) {
+			QAT_LOG(ERR, "Invalid rsa input parameter");
+			err = -EINVAL;
+			goto error;
+		}
 	} else if (xform->xform_type >= RTE_CRYPTO_ASYM_XFORM_TYPE_LIST_END
 			|| xform->xform_type <= RTE_CRYPTO_ASYM_XFORM_NONE) {
 		QAT_LOG(ERR, "Invalid asymmetric crypto xform");
diff --git a/drivers/crypto/qat/qat_asym.h b/drivers/crypto/qat/qat_asym.h
index b04eee4..b12a969 100644
--- a/drivers/crypto/qat/qat_asym.h
+++ b/drivers/crypto/qat/qat_asym.h
@@ -24,6 +24,8 @@ typedef uint64_t large_int_ptr;
 #define QAT_ASYM_MODINV_NUM_OUT_PARAMS		1
 #define QAT_ASYM_MODEXP_NUM_IN_PARAMS		3
 #define QAT_ASYM_MODEXP_NUM_OUT_PARAMS		1
+#define QAT_ASYM_RSA_NUM_IN_PARAMS		3
+#define QAT_ASYM_RSA_NUM_OUT_PARAMS		1
 
 struct qat_asym_op_cookie {
 	size_t alg_size;
diff --git a/drivers/crypto/qat/qat_asym_pmd.c b/drivers/crypto/qat/qat_asym_pmd.c
index 71fd709..78fc2d7 100644
--- a/drivers/crypto/qat/qat_asym_pmd.c
+++ b/drivers/crypto/qat/qat_asym_pmd.c
@@ -271,7 +271,8 @@ qat_asym_dev_create(struct qat_pci_device *qat_pci_dev)
 
 	cryptodev->feature_flags = RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_HW_ACCELERATED |
-			RTE_CRYPTODEV_FF_ASYM_SESSIONLESS;
+			RTE_CRYPTODEV_FF_ASYM_SESSIONLESS |
+			RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP;
 	internals = cryptodev->data->dev_private;
 	internals->qat_dev = qat_pci_dev;
 	qat_pci_dev->asym_dev = internals;
