From 3b53e18a4ff9ceddbcf3480afd1e787983038e2b Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Tue, 19 May 2015 15:51:01 +0100 Subject: [PATCH] Add scrypt tests. Add scrypt test support to evp_test and add test values from from draft-josefsson-scrypt-kdf-03. Reviewed-by: Rich Salz --- test/evp_test.c | 160 +++++++++++++++++++++++++++++++++++++++++++++- test/evptests.txt | 39 +++++++++++ 2 files changed, 198 insertions(+), 1 deletion(-) diff --git a/test/evp_test.c b/test/evp_test.c index e682f43f46..e0e4857657 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -60,6 +60,7 @@ #include #include #include +#include "internal/numbers.h" /* Remove spaces from beginning and end of a string */ @@ -143,7 +144,16 @@ static int test_bin(const char *value, unsigned char **buf, size_t *buflen) if (value[vlen - 1] != '"') return 0; vlen--; - *buf = BUF_memdup(value, vlen); + if (vlen == 0) { + *buf = OPENSSL_malloc(1); + if (*buf == NULL) + return 0; + **buf = 0; + } else { + *buf = BUF_memdup(value, vlen); + if (*buf == NULL) + return 0; + } *buflen = vlen; return 1; } @@ -157,6 +167,30 @@ static int test_bin(const char *value, unsigned char **buf, size_t *buflen) *buflen = len; return 1; } +/* Parse unsigned decimal 64 bit integer value */ +static int test_uint64(const char *value, uint64_t *pr) +{ + const char *p = value; + if (!*p) { + fprintf(stderr, "Invalid empty integer value\n"); + return -1; + } + *pr = 0; + while (*p) { + if (*pr > UINT64_MAX/10) { + fprintf(stderr, "Integer string overflow value=%s\n", value); + return -1; + } + *pr *= 10; + if (*p < '0' || *p > '9') { + fprintf(stderr, "Invalid integer string value=%s\n", value); + return -1; + } + *pr += *p - '0'; + p++; + } + return 1; +} /* Structure holding test information */ struct evp_test { @@ -216,6 +250,7 @@ static const struct evp_test_method mac_test_method; static const struct evp_test_method psign_test_method, pverify_test_method; static const struct evp_test_method pdecrypt_test_method; static const struct evp_test_method pverify_recover_test_method; +static const struct evp_test_method pbe_test_method; static const struct evp_test_method *evp_test_list[] = { &digest_test_method, @@ -225,6 +260,7 @@ static const struct evp_test_method *evp_test_list[] = { &pverify_test_method, &pdecrypt_test_method, &pverify_recover_test_method, + &pbe_test_method, NULL }; @@ -1243,3 +1279,125 @@ static const struct evp_test_method pverify_test_method = { pkey_test_parse, verify_test_run }; + +/* PBE tests */ + +#define PBE_TYPE_SCRYPT 1 + +struct pbe_data { + + int pbe_type; + + /* scrypt parameters */ + uint64_t N, r, p, maxmem; + + /* password */ + unsigned char *pass; + size_t pass_len; + + /* salt */ + unsigned char *salt; + size_t salt_len; + + /* Expected output */ + unsigned char *key; + size_t key_len; +}; + +static int scrypt_test_parse(struct evp_test *t, + const char *keyword, const char *value) +{ + struct pbe_data *pdata = t->data; + if (strcmp(keyword, "N") == 0) + return test_uint64(value, &pdata->N); + if (strcmp(keyword, "p") == 0) + return test_uint64(value, &pdata->p); + if (strcmp(keyword, "r") == 0) + return test_uint64(value, &pdata->r); + if (strcmp(keyword, "maxmem") == 0) + return test_uint64(value, &pdata->maxmem); + return 0; +} + +static int scrypt_test_run(struct evp_test *t) +{ + struct pbe_data *pdata = t->data; + const char *err = "INTERNAL_ERROR"; + unsigned char *key; + key = OPENSSL_malloc(pdata->key_len); + if (!key) + goto err; + err = "SCRYPT_ERROR"; + if (EVP_PBE_scrypt((const char *)pdata->pass, pdata->pass_len, + pdata->salt, pdata->salt_len, + pdata->N, pdata->r, pdata->p, pdata->maxmem, + key, pdata->key_len) == 0) + goto err; + err = "KEY_MISMATCH"; + if (check_output(t, pdata->key, key, pdata->key_len)) + goto err; + err = NULL; + err: + OPENSSL_free(key); + t->err = err; + return 1; +} + +static int pbe_test_init(struct evp_test *t, const char *alg) +{ + struct pbe_data *pdat; + int pbe_type = 0; + if (strcmp(alg, "scrypt") == 0) + pbe_type = PBE_TYPE_SCRYPT; + else + fprintf(stderr, "Unknown pbe algorithm %s\n", alg); + pdat = OPENSSL_malloc(sizeof(*pdat)); + pdat->pbe_type = pbe_type; + pdat->pass = NULL; + pdat->salt = NULL; + pdat->N = 0; + pdat->r = 0; + pdat->p = 0; + pdat->maxmem = 0; + t->data = pdat; + return 1; +} + +static void pbe_test_cleanup(struct evp_test *t) +{ + struct pbe_data *pdat = t->data; + test_free(pdat->pass); + test_free(pdat->salt); + test_free(pdat->key); +} + +static int pbe_test_parse(struct evp_test *t, + const char *keyword, const char *value) +{ + struct pbe_data *pdata = t->data; + if (strcmp(keyword, "Password") == 0) + return test_bin(value, &pdata->pass, &pdata->pass_len); + if (strcmp(keyword, "Salt") == 0) + return test_bin(value, &pdata->salt, &pdata->salt_len); + if (strcmp(keyword, "Key") == 0) + return test_bin(value, &pdata->key, &pdata->key_len); + if (pdata->pbe_type == PBE_TYPE_SCRYPT) + return scrypt_test_parse(t, keyword, value); + return 0; +} + +static int pbe_test_run(struct evp_test *t) +{ + struct pbe_data *pdata = t->data; + if (pdata->pbe_type == PBE_TYPE_SCRYPT) + return scrypt_test_run(t); + return 0; +} + +static const struct evp_test_method pbe_test_method = { + "PBE", + pbe_test_init, + pbe_test_cleanup, + pbe_test_parse, + pbe_test_run +}; diff --git a/test/evptests.txt b/test/evptests.txt index 26d371c559..25b9ef601a 100644 --- a/test/evptests.txt +++ b/test/evptests.txt @@ -2314,3 +2314,42 @@ Ctrl = digest:SHA1 Input = "0123456789ABCDEF1234" Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000 Result = VERIFY_ERROR + +# scrypt tests from draft-josefsson-scrypt-kdf-03 +PBE = scrypt +Password = "" +Salt = "" +N = 16 +r = 1 +p = 1 +Key = 77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906 + +PBE = scrypt +Password = "password" +Salt = "NaCl" +N = 1024 +r = 8 +p = 16 +Key = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640 + +PBE = scrypt +Password = "pleaseletmein" +Salt = "SodiumChloride" +N = 16384 +r = 8 +p = 1 +Key = 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887 + +# NB: this test requires more than 2GB of memory to run so it will hit the +# scrypt memory limit and return an error. To run this test without error +# uncomment out the "maxmem" line and comment out the "Result" +# line +PBE = scrypt +Password = "pleaseletmein" +Salt = "SodiumChloride" +N = 1048576 +r = 8 +p = 1 +Key = 2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4 +#maxmem = 10000000000 +Result = SCRYPT_ERROR -- 2.25.1