#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/x509v3.h>
+#include <openssl/pkcs12.h>
+#include "internal/numbers.h"
/* Remove spaces from beginning and end of a string */
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;
}
*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 {
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,
&pverify_test_method,
&pdecrypt_test_method,
&pverify_recover_test_method,
+ &pbe_test_method,
NULL
};
static const struct evp_test_method *evp_find_test(const char *name)
{
const struct evp_test_method **tt;
+
for (tt = evp_test_list; *tt; tt++) {
- if (!strcmp(name, (*tt)->name))
+ if (strcmp(name, (*tt)->name) == 0)
return *tt;
}
return NULL;
t->start_line, t->expected_err);
return 0;
}
- if (!strcmp(t->err, t->expected_err))
+ if (strcmp(t->err, t->expected_err) == 0)
return 1;
fprintf(stderr, "Test line %d: expecting %s got %s\n",
static int find_key(EVP_PKEY **ppk, const char *name, struct key_list *lst)
{
for (; lst; lst = lst->next) {
- if (!strcmp(lst->name, name)) {
+ if (strcmp(lst->name, name) == 0) {
if (ppk)
*ppk = lst->key;
return 1;
static int process_test(struct evp_test *t, char *buf, int verbose)
{
- char *keyword, *value;
+ char *keyword = NULL, *value = NULL;
int rv = 0, add_key = 0;
- long save_pos;
- struct key_list **lst, *key;
+ long save_pos = 0;
+ struct key_list **lst = NULL, *key = NULL;
EVP_PKEY *pk = NULL;
- const struct evp_test_method *tmeth;
+ const struct evp_test_method *tmeth = NULL;
if (verbose)
fputs(buf, stdout);
if (!parse_line(&keyword, &value, buf))
return 1;
- if (!strcmp(keyword, "PrivateKey")) {
+ if (strcmp(keyword, "PrivateKey") == 0) {
save_pos = ftell(t->in);
pk = PEM_read_PrivateKey(t->in, NULL, 0, NULL);
if (pk == NULL && !check_unsupported()) {
lst = &t->private;
add_key = 1;
}
- if (!strcmp(keyword, "PublicKey")) {
+ if (strcmp(keyword, "PublicKey") == 0) {
save_pos = ftell(t->in);
pk = PEM_read_PUBKEY(t->in, NULL, 0, NULL);
if (pk == NULL && !check_unsupported()) {
fprintf(stderr, "Duplicate key %s\n", value);
return 0;
}
- key = OPENSSL_malloc(sizeof(struct key_list));
+ key = OPENSSL_malloc(sizeof(*key));
if (!key)
return 0;
key->name = BUF_strdup(value);
fseek(t->in, save_pos, SEEK_SET);
while (fgets(tmpbuf, sizeof(tmpbuf), t->in)) {
t->line++;
- if (!strncmp(tmpbuf, "-----END", 8))
+ if (strncmp(tmpbuf, "-----END", 8) == 0)
return 1;
}
fprintf(stderr, "Can't find key end\n");
return 1;
} else if (t->skip) {
return 1;
- } else if (!strcmp(keyword, "Result")) {
+ } else if (strcmp(keyword, "Result") == 0) {
if (t->expected_err) {
fprintf(stderr, "Line %d: multiple result lines\n", t->line);
return 0;
}
return 0;
}
- mdat = OPENSSL_malloc(sizeof(struct digest_data));
+ mdat = OPENSSL_malloc(sizeof(*mdat));
mdat->digest = digest;
mdat->input = NULL;
mdat->output = NULL;
const char *keyword, const char *value)
{
struct digest_data *mdata = t->data;
- if (!strcmp(keyword, "Input"))
+ if (strcmp(keyword, "Input") == 0)
return test_bin(value, &mdata->input, &mdata->input_len);
- if (!strcmp(keyword, "Output"))
+ if (strcmp(keyword, "Output") == 0)
return test_bin(value, &mdata->output, &mdata->output_len);
- if (!strcmp(keyword, "Count")) {
+ if (strcmp(keyword, "Count") == 0) {
long nrpt = atoi(value);
if (nrpt <= 0)
return 0;
}
return 0;
}
- cdat = OPENSSL_malloc(sizeof(struct cipher_data));
+ cdat = OPENSSL_malloc(sizeof(*cdat));
cdat->cipher = cipher;
cdat->enc = -1;
cdat->key = NULL;
const char *value)
{
struct cipher_data *cdat = t->data;
- if (!strcmp(keyword, "Key"))
+ if (strcmp(keyword, "Key") == 0)
return test_bin(value, &cdat->key, &cdat->key_len);
- if (!strcmp(keyword, "IV"))
+ if (strcmp(keyword, "IV") == 0)
return test_bin(value, &cdat->iv, &cdat->iv_len);
- if (!strcmp(keyword, "Plaintext"))
+ if (strcmp(keyword, "Plaintext") == 0)
return test_bin(value, &cdat->plaintext, &cdat->plaintext_len);
- if (!strcmp(keyword, "Ciphertext"))
+ if (strcmp(keyword, "Ciphertext") == 0)
return test_bin(value, &cdat->ciphertext, &cdat->ciphertext_len);
if (cdat->aead) {
- if (!strcmp(keyword, "AAD"))
+ if (strcmp(keyword, "AAD") == 0)
return test_bin(value, &cdat->aad, &cdat->aad_len);
- if (!strcmp(keyword, "Tag"))
+ if (strcmp(keyword, "Tag") == 0)
return test_bin(value, &cdat->tag, &cdat->tag_len);
}
- if (!strcmp(keyword, "Operation")) {
- if (!strcmp(value, "ENCRYPT"))
+ if (strcmp(keyword, "Operation") == 0) {
+ if (strcmp(value, "ENCRYPT") == 0)
cdat->enc = 1;
- else if (!strcmp(value, "DECRYPT"))
+ else if (strcmp(value, "DECRYPT") == 0)
cdat->enc = 0;
else
return 0;
{
int type;
struct mac_data *mdat;
- if (!strcmp(alg, "HMAC"))
+ if (strcmp(alg, "HMAC") == 0)
type = EVP_PKEY_HMAC;
- else if (!strcmp(alg, "CMAC"))
+ else if (strcmp(alg, "CMAC") == 0)
type = EVP_PKEY_CMAC;
else
return 0;
- mdat = OPENSSL_malloc(sizeof(struct mac_data));
+ mdat = OPENSSL_malloc(sizeof(*mdat));
mdat->type = type;
mdat->alg = NULL;
mdat->key = NULL;
const char *keyword, const char *value)
{
struct mac_data *mdata = t->data;
- if (!strcmp(keyword, "Key"))
+ if (strcmp(keyword, "Key") == 0)
return test_bin(value, &mdata->key, &mdata->key_len);
- if (!strcmp(keyword, "Algorithm")) {
+ if (strcmp(keyword, "Algorithm") == 0) {
mdata->alg = BUF_strdup(value);
if (!mdata->alg)
return 0;
return 1;
}
- if (!strcmp(keyword, "Input"))
+ if (strcmp(keyword, "Input") == 0)
return test_bin(value, &mdata->input, &mdata->input_len);
- if (!strcmp(keyword, "Output"))
+ if (strcmp(keyword, "Output") == 0)
return test_bin(value, &mdata->output, &mdata->output_len);
return 0;
}
return 1;
}
- kdata = OPENSSL_malloc(sizeof(struct pkey_data));
+ kdata = OPENSSL_malloc(sizeof(*kdata));
if (!kdata) {
EVP_PKEY_free(pkey);
return 0;
const char *keyword, const char *value)
{
struct pkey_data *kdata = t->data;
- if (!strcmp(keyword, "Input"))
+ if (strcmp(keyword, "Input") == 0)
return test_bin(value, &kdata->input, &kdata->input_len);
- if (!strcmp(keyword, "Output"))
+ if (strcmp(keyword, "Output") == 0)
return test_bin(value, &kdata->output, &kdata->output_len);
- if (!strcmp(keyword, "Ctrl")) {
+ if (strcmp(keyword, "Ctrl") == 0) {
char *p = strchr(value, ':');
if (p)
*p++ = 0;
pkey_test_parse,
verify_test_run
};
+
+/* PBE tests */
+
+#define PBE_TYPE_SCRYPT 1
+#define PBE_TYPE_PBKDF2 2
+#define PBE_TYPE_PKCS12 3
+
+struct pbe_data {
+
+ int pbe_type;
+
+ /* scrypt parameters */
+ uint64_t N, r, p, maxmem;
+
+ /* PKCS#12 parameters */
+ int id, iter;
+ const EVP_MD *md;
+
+ /* 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 pbkdf2_test_parse(struct evp_test *t,
+ const char *keyword, const char *value)
+{
+ struct pbe_data *pdata = t->data;
+
+ if (strcmp(keyword, "iter") == 0) {
+ pdata->iter = atoi(value);
+ if (pdata->iter <= 0)
+ return 0;
+ return 1;
+ }
+ if (strcmp(keyword, "MD") == 0) {
+ pdata->md = EVP_get_digestbyname(value);
+ if (pdata->md == NULL)
+ return 0;
+ return 1;
+ }
+ return 0;
+}
+
+static int pkcs12_test_parse(struct evp_test *t,
+ const char *keyword, const char *value)
+{
+ struct pbe_data *pdata = t->data;
+
+ if (strcmp(keyword, "id") == 0) {
+ pdata->id = atoi(value);
+ if (pdata->id <= 0)
+ return 0;
+ return 1;
+ }
+ return pbkdf2_test_parse(t, keyword, value);
+}
+
+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 if (strcmp(alg, "pbkdf2") == 0)
+ pbe_type = PBE_TYPE_PBKDF2;
+ else if (strcmp(alg, "pkcs12") == 0)
+ pbe_type = PBE_TYPE_PKCS12;
+ 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;
+ pdat->id = 0;
+ pdat->iter = 0;
+ pdat->md = NULL;
+ 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);
+ else if (pdata->pbe_type == PBE_TYPE_PBKDF2)
+ return pbkdf2_test_parse(t, keyword, value);
+ else if (pdata->pbe_type == PBE_TYPE_PKCS12)
+ return pkcs12_test_parse(t, keyword, value);
+ return 0;
+}
+
+static int pbe_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;
+ if (pdata->pbe_type == PBE_TYPE_PBKDF2) {
+ err = "PBKDF2_ERROR";
+ if (PKCS5_PBKDF2_HMAC((char *)pdata->pass, pdata->pass_len,
+ pdata->salt, pdata->salt_len,
+ pdata->iter, pdata->md,
+ pdata->key_len, key) == 0)
+ goto err;
+ } else if (pdata->pbe_type == PBE_TYPE_SCRYPT) {
+ 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;
+ } else if (pdata->pbe_type == PBE_TYPE_PKCS12) {
+ err = "PKCS12_ERROR";
+ if (PKCS12_key_gen_uni(pdata->pass, pdata->pass_len,
+ pdata->salt, pdata->salt_len,
+ pdata->id, pdata->iter, pdata->key_len,
+ key, pdata->md) == 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 const struct evp_test_method pbe_test_method = {
+ "PBE",
+ pbe_test_init,
+ pbe_test_cleanup,
+ pbe_test_parse,
+ pbe_test_run
+};