Commit 3b53e18a authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add scrypt tests.



Add scrypt test support to evp_test and add test values from
from draft-josefsson-scrypt-kdf-03.

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
parent a95fb9e3
Loading
Loading
Loading
Loading
+159 −1
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@
#include <openssl/pem.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/err.h>
#include <openssl/x509v3.h>
#include <openssl/x509v3.h>
#include "internal/numbers.h"


/* Remove spaces from beginning and end of a string */
/* 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] != '"')
        if (value[vlen - 1] != '"')
            return 0;
            return 0;
        vlen--;
        vlen--;
        if (vlen == 0) {
            *buf = OPENSSL_malloc(1);
            if (*buf == NULL)
                return 0;
            **buf = 0;
        } else {
            *buf = BUF_memdup(value, vlen);
            *buf = BUF_memdup(value, vlen);
            if (*buf == NULL)
                return 0;
        }
        *buflen = vlen;
        *buflen = vlen;
        return 1;
        return 1;
    }
    }
@@ -157,6 +167,30 @@ static int test_bin(const char *value, unsigned char **buf, size_t *buflen)
    *buflen = len;
    *buflen = len;
    return 1;
    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 */
/* Structure holding test information */
struct evp_test {
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 psign_test_method, pverify_test_method;
static const struct evp_test_method pdecrypt_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 pverify_recover_test_method;
static const struct evp_test_method pbe_test_method;


static const struct evp_test_method *evp_test_list[] = {
static const struct evp_test_method *evp_test_list[] = {
    &digest_test_method,
    &digest_test_method,
@@ -225,6 +260,7 @@ static const struct evp_test_method *evp_test_list[] = {
    &pverify_test_method,
    &pverify_test_method,
    &pdecrypt_test_method,
    &pdecrypt_test_method,
    &pverify_recover_test_method,
    &pverify_recover_test_method,
    &pbe_test_method,
    NULL
    NULL
};
};


@@ -1243,3 +1279,125 @@ static const struct evp_test_method pverify_test_method = {
    pkey_test_parse,
    pkey_test_parse,
    verify_test_run
    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
};
+39 −0
Original line number Original line Diff line number Diff line
@@ -2314,3 +2314,42 @@ Ctrl = digest:SHA1
Input = "0123456789ABCDEF1234"
Input = "0123456789ABCDEF1234"
Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000
Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000
Result = VERIFY_ERROR
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