|
@@ -27,6 +27,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/string.h>
|
|
#include <linux/string.h>
|
|
#include <crypto/rng.h>
|
|
#include <crypto/rng.h>
|
|
|
|
+#include <crypto/drbg.h>
|
|
|
|
|
|
#include "internal.h"
|
|
#include "internal.h"
|
|
|
|
|
|
@@ -108,6 +109,11 @@ struct cprng_test_suite {
|
|
unsigned int count;
|
|
unsigned int count;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+struct drbg_test_suite {
|
|
|
|
+ struct drbg_testvec *vecs;
|
|
|
|
+ unsigned int count;
|
|
|
|
+};
|
|
|
|
+
|
|
struct alg_test_desc {
|
|
struct alg_test_desc {
|
|
const char *alg;
|
|
const char *alg;
|
|
int (*test)(const struct alg_test_desc *desc, const char *driver,
|
|
int (*test)(const struct alg_test_desc *desc, const char *driver,
|
|
@@ -121,6 +127,7 @@ struct alg_test_desc {
|
|
struct pcomp_test_suite pcomp;
|
|
struct pcomp_test_suite pcomp;
|
|
struct hash_test_suite hash;
|
|
struct hash_test_suite hash;
|
|
struct cprng_test_suite cprng;
|
|
struct cprng_test_suite cprng;
|
|
|
|
+ struct drbg_test_suite drbg;
|
|
} suite;
|
|
} suite;
|
|
};
|
|
};
|
|
|
|
|
|
@@ -1715,6 +1722,100 @@ static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+static int drbg_cavs_test(struct drbg_testvec *test, int pr,
|
|
|
|
+ const char *driver, u32 type, u32 mask)
|
|
|
|
+{
|
|
|
|
+ int ret = -EAGAIN;
|
|
|
|
+ struct crypto_rng *drng;
|
|
|
|
+ struct drbg_test_data test_data;
|
|
|
|
+ struct drbg_string addtl, pers, testentropy;
|
|
|
|
+ unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
|
|
|
|
+
|
|
|
|
+ if (!buf)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ drng = crypto_alloc_rng(driver, type, mask);
|
|
|
|
+ if (IS_ERR(drng)) {
|
|
|
|
+ printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for"
|
|
|
|
+ "%s\n", driver);
|
|
|
|
+ kzfree(buf);
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ test_data.testentropy = &testentropy;
|
|
|
|
+ drbg_string_fill(&testentropy, test->entropy, test->entropylen);
|
|
|
|
+ drbg_string_fill(&pers, test->pers, test->perslen);
|
|
|
|
+ ret = crypto_drbg_reset_test(drng, &pers, &test_data);
|
|
|
|
+ if (ret) {
|
|
|
|
+ printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
|
|
|
|
+ goto outbuf;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ drbg_string_fill(&addtl, test->addtla, test->addtllen);
|
|
|
|
+ if (pr) {
|
|
|
|
+ drbg_string_fill(&testentropy, test->entpra, test->entprlen);
|
|
|
|
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
|
|
|
|
+ buf, test->expectedlen, &addtl, &test_data);
|
|
|
|
+ } else {
|
|
|
|
+ ret = crypto_drbg_get_bytes_addtl(drng,
|
|
|
|
+ buf, test->expectedlen, &addtl);
|
|
|
|
+ }
|
|
|
|
+ if (ret <= 0) {
|
|
|
|
+ printk(KERN_ERR "alg: drbg: could not obtain random data for"
|
|
|
|
+ "driver %s\n", driver);
|
|
|
|
+ goto outbuf;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ drbg_string_fill(&addtl, test->addtlb, test->addtllen);
|
|
|
|
+ if (pr) {
|
|
|
|
+ drbg_string_fill(&testentropy, test->entprb, test->entprlen);
|
|
|
|
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
|
|
|
|
+ buf, test->expectedlen, &addtl, &test_data);
|
|
|
|
+ } else {
|
|
|
|
+ ret = crypto_drbg_get_bytes_addtl(drng,
|
|
|
|
+ buf, test->expectedlen, &addtl);
|
|
|
|
+ }
|
|
|
|
+ if (ret <= 0) {
|
|
|
|
+ printk(KERN_ERR "alg: drbg: could not obtain random data for"
|
|
|
|
+ "driver %s\n", driver);
|
|
|
|
+ goto outbuf;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = memcmp(test->expected, buf, test->expectedlen);
|
|
|
|
+
|
|
|
|
+outbuf:
|
|
|
|
+ crypto_free_rng(drng);
|
|
|
|
+ kzfree(buf);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
|
|
|
|
+ u32 type, u32 mask)
|
|
|
|
+{
|
|
|
|
+ int err = 0;
|
|
|
|
+ int pr = 0;
|
|
|
|
+ int i = 0;
|
|
|
|
+ struct drbg_testvec *template = desc->suite.drbg.vecs;
|
|
|
|
+ unsigned int tcount = desc->suite.drbg.count;
|
|
|
|
+
|
|
|
|
+ if (0 == memcmp(driver, "drbg_pr_", 8))
|
|
|
|
+ pr = 1;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < tcount; i++) {
|
|
|
|
+ err = drbg_cavs_test(&template[i], pr, driver, type, mask);
|
|
|
|
+ if (err) {
|
|
|
|
+ printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
|
|
|
|
+ i, driver);
|
|
|
|
+ err = -EINVAL;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
static int alg_test_null(const struct alg_test_desc *desc,
|
|
static int alg_test_null(const struct alg_test_desc *desc,
|
|
const char *driver, u32 type, u32 mask)
|
|
const char *driver, u32 type, u32 mask)
|
|
{
|
|
{
|
|
@@ -2457,6 +2558,152 @@ static const struct alg_test_desc alg_test_descs[] = {
|
|
}, {
|
|
}, {
|
|
.alg = "digest_null",
|
|
.alg = "digest_null",
|
|
.test = alg_test_null,
|
|
.test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_ctr_aes128",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_nopr_ctr_aes128_tv_template,
|
|
|
|
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes128_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_ctr_aes192",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_nopr_ctr_aes192_tv_template,
|
|
|
|
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes192_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_ctr_aes256",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_nopr_ctr_aes256_tv_template,
|
|
|
|
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes256_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ /*
|
|
|
|
+ * There is no need to specifically test the DRBG with every
|
|
|
|
+ * backend cipher -- covered by drbg_nopr_hmac_sha256 test
|
|
|
|
+ */
|
|
|
|
+ .alg = "drbg_nopr_hmac_sha1",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_hmac_sha256",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_nopr_hmac_sha256_tv_template,
|
|
|
|
+ .count =
|
|
|
|
+ ARRAY_SIZE(drbg_nopr_hmac_sha256_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ /* covered by drbg_nopr_hmac_sha256 test */
|
|
|
|
+ .alg = "drbg_nopr_hmac_sha384",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_hmac_sha512",
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_sha1",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_sha256",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_nopr_sha256_tv_template,
|
|
|
|
+ .count = ARRAY_SIZE(drbg_nopr_sha256_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ /* covered by drbg_nopr_sha256 test */
|
|
|
|
+ .alg = "drbg_nopr_sha384",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_nopr_sha512",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_ctr_aes128",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_pr_ctr_aes128_tv_template,
|
|
|
|
+ .count = ARRAY_SIZE(drbg_pr_ctr_aes128_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ /* covered by drbg_pr_ctr_aes128 test */
|
|
|
|
+ .alg = "drbg_pr_ctr_aes192",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_ctr_aes256",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_hmac_sha1",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_hmac_sha256",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_pr_hmac_sha256_tv_template,
|
|
|
|
+ .count = ARRAY_SIZE(drbg_pr_hmac_sha256_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ /* covered by drbg_pr_hmac_sha256 test */
|
|
|
|
+ .alg = "drbg_pr_hmac_sha384",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_hmac_sha512",
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_sha1",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_sha256",
|
|
|
|
+ .test = alg_test_drbg,
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .suite = {
|
|
|
|
+ .drbg = {
|
|
|
|
+ .vecs = drbg_pr_sha256_tv_template,
|
|
|
|
+ .count = ARRAY_SIZE(drbg_pr_sha256_tv_template)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ /* covered by drbg_pr_sha256 test */
|
|
|
|
+ .alg = "drbg_pr_sha384",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
|
|
+ }, {
|
|
|
|
+ .alg = "drbg_pr_sha512",
|
|
|
|
+ .fips_allowed = 1,
|
|
|
|
+ .test = alg_test_null,
|
|
}, {
|
|
}, {
|
|
.alg = "ecb(__aes-aesni)",
|
|
.alg = "ecb(__aes-aesni)",
|
|
.test = alg_test_null,
|
|
.test = alg_test_null,
|