Skip to content

Commit

Permalink
Add a generic digest utility function
Browse files Browse the repository at this point in the history
In preparation to reuse outside of the specific object.c use case.
Also adds a better and more flexible interface.

Signed-off-by: Simo Sorce <[email protected]>
  • Loading branch information
simo5 committed Sep 27, 2024
1 parent 8757cf2 commit 3bb0fa5
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 113 deletions.
168 changes: 55 additions & 113 deletions src/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -2663,100 +2663,12 @@ static CK_RV param_to_attr(P11PROV_CTX *ctx, const OSSL_PARAM params[],
return CKR_OK;
}

static CK_RV digest(P11PROV_CTX *ctx, const uint8_t *prefx, size_t plen,
const uint8_t *data1, size_t len1, const uint8_t *data2,
size_t len2, const uint8_t *data3, size_t len3,
uint8_t **out, size_t *outlen)
{
EVP_MD_CTX *mdctx = NULL;
EVP_MD *md = NULL;
unsigned char *dgst = NULL;
unsigned int dlen = 0;
CK_RV rv;
int err;

md = EVP_MD_fetch(p11prov_ctx_get_libctx(ctx), "sha256", NULL);
if (!md) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Failed to fetch sha256 digest");
goto done;
}
dlen = EVP_MD_get_size(md);
if (dlen == -1) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Failed to get sha256 digest length");
goto done;
}
dgst = OPENSSL_malloc(dlen);
if (!dgst) {
rv = CKR_HOST_MEMORY;
goto done;
}
mdctx = EVP_MD_CTX_new();
if (!mdctx) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_MD_CTX_new failed");
goto done;
}
err = EVP_DigestInit(mdctx, md);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestInit failed");
goto done;
}
if (len1 > 0) {
err = EVP_DigestUpdate(mdctx, data1, len1);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestUpdate(1) failed");
goto done;
}
}
if (len2 > 0) {
err = EVP_DigestUpdate(mdctx, data2, len2);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestUpdate(2) failed");
goto done;
}
}
if (len3 > 0) {
err = EVP_DigestUpdate(mdctx, data3, len3);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestUpdate(3) failed");
goto done;
}
}
err = EVP_DigestFinal(mdctx, dgst, &dlen);
if (err != RET_OSSL_OK || dlen == 0) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestFinal(2) failed");
goto done;
}

*out = dgst;
*outlen = dlen;
dgst = NULL;
rv = CKR_OK;

done:
OPENSSL_free(dgst);
EVP_MD_CTX_free(mdctx);
EVP_MD_free(md);
return rv;
}

static CK_RV prep_rsa_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
struct pool_find_ctx *findctx)
{
const OSSL_PARAM *pn;
const OSSL_PARAM *pe;
const OSSL_PARAM *pd;
const char *prefix = "PrivKey";
size_t prefix_len = 7;
uint8_t *attr_data = NULL;
size_t attr_size = 0;
data_buffer digest_data[5];
data_buffer digest = { 0 };
const OSSL_PARAM *p;
size_t key_size;
CK_RV rv;

Expand Down Expand Up @@ -2786,39 +2698,50 @@ static CK_RV prep_rsa_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
/* A Token would never allow us to search by private exponent,
* so we store a hash of the private key in CKA_ID */

pn = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
if (!pn) {
/* prefix */
digest_data[0].data = (uint8_t *)"PrivKey";
digest_data[0].length = 7;

p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_RSA_N);
return CKR_KEY_INDIGESTIBLE;
}
digest_data[1].data = p->data;
digest_data[1].length = p->data_size;
key_size = p->data_size;

pe = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
if (!pe) {
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_RSA_E);
return CKR_KEY_INDIGESTIBLE;
}
digest_data[2].data = p->data;
digest_data[2].length = p->data_size;

pd = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
if (!pd) {
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_RSA_D);
return CKR_KEY_INDIGESTIBLE;
}
digest_data[3].data = p->data;
digest_data[3].length = p->data_size;

digest_data[4].data = NULL;

rv = p11prov_digest_util(ctx, "sha256", NULL, digest_data, &digest);

rv = digest(ctx, (uint8_t *)prefix, prefix_len, pn->data, pn->data_size,
pe->data, pe->data_size, pd->data, pd->data_size,
&attr_data, &attr_size);
if (rv != CKR_OK) {
return rv;
}
findctx->attrs[0].type = CKA_ID;
findctx->attrs[0].pValue = attr_data;
findctx->attrs[0].ulValueLen = attr_size;
findctx->attrs[0].pValue = digest.data;
findctx->attrs[0].ulValueLen = digest.length;
findctx->numattrs++;

key_size = pn->data_size;
break;
default:
return CKR_GENERAL_ERROR;
Expand All @@ -2844,15 +2767,13 @@ static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
OSSL_PARAM pub_key[2] = { 0 };
uint8_t pub_data[MAX_EC_PUB_KEY_SIZE];

const char *prefix = "PrivKey";
size_t prefix_len = 7;
uint8_t *attr_data = NULL;
size_t attr_size = 0;
data_buffer digest_data[5];
data_buffer digest = { 0 };

const char *curve_name = NULL;
int curve_nid;
unsigned char *ecparams = NULL;
int len;
int len, i;
CK_RV rv;

if (findctx->numattrs != MAX_ATTRS_SIZE) {
Expand Down Expand Up @@ -2956,15 +2877,36 @@ static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
return CKR_KEY_INDIGESTIBLE;
}

rv = digest(ctx, (uint8_t *)prefix, prefix_len, (uint8_t *)curve_name,
curve_name ? strlen(curve_name) : 0, ecparams, len, p->data,
p->data_size, &attr_data, &attr_size);
i = 0;

/* prefix */
digest_data[i].data = (uint8_t *)"PrivKey";
digest_data[i].length = 7;
i++;

if (curve_name) {
digest_data[i].data = (uint8_t *)curve_name;
digest_data[i].length = strlen(curve_name);
i++;
}

digest_data[i].data = ecparams;
digest_data[i].length = len;
i++;

digest_data[i].data = p->data;
digest_data[i].length = p->data_size;
i++;

digest_data[i].data = NULL;

rv = p11prov_digest_util(ctx, "sha256", NULL, digest_data, &digest);
if (rv != CKR_OK) {
return rv;
}
findctx->attrs[0].type = CKA_ID;
findctx->attrs[0].pValue = attr_data;
findctx->attrs[0].ulValueLen = attr_size;
findctx->attrs[0].pValue = digest.data;
findctx->attrs[0].ulValueLen = digest.length;
findctx->numattrs++;

break;
Expand Down
89 changes: 89 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,3 +1170,92 @@ void p11prov_force_rwlock_reinit(pthread_rwlock_t *lock)
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
memcpy(lock, &rwlock, sizeof(rwlock));
}

CK_RV p11prov_digest_util(P11PROV_CTX *ctx, const char *digest,
const char *properties, data_buffer data[],
data_buffer *output)
{
EVP_MD_CTX *mdctx = NULL;
EVP_MD *md = NULL;
unsigned char *dgst = NULL;
unsigned int dlen = 0;
CK_RV rv;
int err;

if (!data || !output) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Invalid function arguments");
goto done;
}

md = EVP_MD_fetch(p11prov_ctx_get_libctx(ctx), digest, properties);
if (!md) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Failed to fetch %s digest", digest);
goto done;
}

dlen = EVP_MD_get_size(md);
if (dlen == -1) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Failed to get %s digest length", digest);
goto done;
}

if (output->data) {
if (output->length < dlen) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Invalid function arguments");
goto done;
}
dgst = output->data;
} else {
dgst = OPENSSL_malloc(dlen);
if (!dgst) {
rv = CKR_HOST_MEMORY;
goto done;
}
}

mdctx = EVP_MD_CTX_new();
if (!mdctx) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_MD_CTX_new failed");
goto done;
}

err = EVP_DigestInit(mdctx, md);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestInit failed");
goto done;
}

for (int i = 0; data[i].data; i++) {
err = EVP_DigestUpdate(mdctx, data[i].data, data[i].length);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestUpdate(%d) failed", i);
goto done;
}
}

err = EVP_DigestFinal(mdctx, dgst, &dlen);
if (err != RET_OSSL_OK || dlen == 0) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestFinal failed");
goto done;
}

output->data = dgst;
output->length = dlen;
rv = CKR_OK;

done:
if (output->data != dgst) {
OPENSSL_free(dgst);
}
EVP_MD_CTX_free(mdctx);
EVP_MD_free(md);
return rv;
}
10 changes: 10 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,14 @@ static inline void constant_select_buf(CK_ULONG cond, CK_ULONG size,
}
}

struct data_buffer {
uint8_t *data;
size_t length;
};
typedef struct data_buffer data_buffer;

CK_RV p11prov_digest_util(P11PROV_CTX *provctx, const char *digest,
const char *properties, data_buffer data[],
data_buffer *output);

#endif /* _UTIL_H */

0 comments on commit 3bb0fa5

Please sign in to comment.