crypto: tegra-se: RNG support for less than 16 Bytes
vjagadish [Sat, 26 Nov 2011 07:19:45 +0000 (12:19 +0530)]
RNG support for less than 16 Bytes and or not a multiple of
16 Bytes.

Bug 893463

Change-Id: I37fff0f90004dd3116b621c5aa956cebbd6a085a
Reviewed-on: http://git-master/r/74263
Reviewed-by: Automatic_Commit_Validation_User
Tested-by: Venkata Jagadish <vjagadish@nvidia.com>
Reviewed-by: Mallikarjun Kasoju <mkasoju@nvidia.com>
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Reviewed-on: http://git-master/r/74559
Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>
Tested-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-by: Venkata Jagadish <vjagadish@nvidia.com>

drivers/crypto/tegra-se.c

index a765945..60ad219 100644 (file)
@@ -1073,12 +1073,14 @@ static int tegra_se_rng_get_random(struct crypto_rng *tfm, u8 *rdata, u32 dlen)
        struct tegra_se_ll *src_ll, *dst_ll;
        unsigned char *dt_buf = (unsigned char *)rng_ctx->dt_buf;
        u8 *rdata_addr;
-       int ret = 0, i, j, num_blocks;
+       int ret = 0, i, j, num_blocks, data_len = 0;
 
-       if (dlen < TEGRA_SE_RNG_DT_SIZE)
-               return -EINVAL;
        num_blocks = (dlen / TEGRA_SE_RNG_DT_SIZE);
 
+       data_len = (dlen % TEGRA_SE_RNG_DT_SIZE);
+       if (data_len == 0)
+               num_blocks = num_blocks - 1;
+
        /* take access to the hw */
        mutex_lock(&se_hw_lock);
        pm_runtime_get_sync(se_dev->dev);
@@ -1096,14 +1098,19 @@ static int tegra_se_rng_get_random(struct crypto_rng *tfm, u8 *rdata, u32 dlen)
                TEGRA_SE_KEY_128_SIZE);
        tegra_se_config_crypto(se_dev, SE_AES_OP_MODE_RNG_X931, true,
                                rng_ctx->slot->slot_num, rng_ctx->use_org_iv);
-       for (j = 0; j < num_blocks; j++) {
+       for (j = 0; j <= num_blocks; j++) {
                ret = tegra_se_start_operation(se_dev,
                                TEGRA_SE_RNG_DT_SIZE, false);
 
                if (!ret) {
                        rdata_addr = (rdata + (j * TEGRA_SE_RNG_DT_SIZE));
-                       memcpy(rdata_addr,
-                               rng_ctx->rng_buf, TEGRA_SE_RNG_DT_SIZE);
+
+                       if (data_len && num_blocks == j) {
+                               memcpy(rdata_addr, rng_ctx->rng_buf, data_len);
+                       } else {
+                               memcpy(rdata_addr,
+                                       rng_ctx->rng_buf, TEGRA_SE_RNG_DT_SIZE);
+                       }
 
                        /* update DT vector */
                        for (i = TEGRA_SE_RNG_DT_SIZE - 1; i >= 0; i--) {