Rework cipher / digest fetching for legacy nids with multiple name support

With multiple names, it's no longer viable to just grab the "first" in
the set and use that to find the legacy NID.  Instead, all names for
an algorithm must be checked, and if we encounter more than one NID
asssociated with those names, we consider it an error and make that
method unloadable.

This ensures that all methods that do have an internal NID associated
will get that NID in their structure, thereby ensuring that other
parts of libcrypto that haven't gone away from using NIDs for
comparison will continue to work as expected.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9969)
This commit is contained in:
Richard Levitte 2019-09-21 20:57:51 +02:00
parent 15dbf3a5a1
commit 3204083820
4 changed files with 81 additions and 20 deletions

View File

@ -636,6 +636,31 @@ EVP_MD *evp_md_new(void)
return md;
}
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*/
#ifndef FIPS_MODE
/* TODO(3.x) get rid of the need for legacy NIDs */
static void set_legacy_nid(const char *name, void *vlegacy_nid)
{
int nid;
int *legacy_nid = vlegacy_nid;
if (*legacy_nid == -1) /* We found a clash already */
return;
if ((nid = OBJ_sn2nid(name)) == NID_undef
&& (nid = OBJ_ln2nid(name)) == NID_undef)
return;
if (*legacy_nid != NID_undef && *legacy_nid != nid) {
*legacy_nid = -1;
return;
}
*legacy_nid = nid;
}
#endif
static void *evp_md_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov, void *unused)
@ -648,21 +673,20 @@ static void *evp_md_from_dispatch(int name_id,
EVPerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
md->name_id = name_id;
#ifndef FIPS_MODE
{
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*
* TODO(3.x) get rid of the need for legacy NIDs
*/
md->type = OBJ_sn2nid(evp_first_name(prov, name_id));
/* TODO(3.x) get rid of the need for legacy NIDs */
md->type = NID_undef;
evp_doall_names(prov, name_id, set_legacy_nid, &md->type);
if (md->type == -1) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
EVP_MD_free(md);
return NULL;
}
#endif
md->name_id = name_id;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_DIGEST_NEWCTX:

View File

@ -1293,6 +1293,31 @@ EVP_CIPHER *evp_cipher_new(void)
return cipher;
}
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*/
#ifndef FIPS_MODE
/* TODO(3.x) get rid of the need for legacy NIDs */
static void set_legacy_nid(const char *name, void *vlegacy_nid)
{
int nid;
int *legacy_nid = vlegacy_nid;
if (*legacy_nid == -1) /* We found a clash already */
return;
if ((nid = OBJ_sn2nid(name)) == NID_undef
&& (nid = OBJ_ln2nid(name)) == NID_undef)
return;
if (*legacy_nid != NID_undef && *legacy_nid != nid) {
*legacy_nid = -1;
return;
}
*legacy_nid = nid;
}
#endif
static void *evp_cipher_from_dispatch(const int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov,
@ -1305,21 +1330,20 @@ static void *evp_cipher_from_dispatch(const int name_id,
EVPerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
cipher->name_id = name_id;
#ifndef FIPS_MODE
{
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*
* TODO(3.x) get rid of the need for legacy NIDs
*/
cipher->nid = OBJ_sn2nid(evp_first_name(prov, name_id));
/* TODO(3.x) get rid of the need for legacy NIDs */
cipher->nid = NID_undef;
evp_doall_names(prov, name_id, set_legacy_nid, &cipher->nid);
if (cipher->nid == -1) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
EVP_CIPHER_free(cipher);
return NULL;
}
#endif
cipher->name_id = name_id;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_CIPHER_NEWCTX:

View File

@ -393,3 +393,13 @@ int evp_is_a(OSSL_PROVIDER *prov, int number, const char *name)
return ossl_namemap_name2num(namemap, name) == number;
}
void evp_doall_names(OSSL_PROVIDER *prov, int number,
void (*fn)(const char *name, void *data),
void *data)
{
OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
ossl_namemap_doall_names(namemap, number, fn, data);
}

View File

@ -251,3 +251,6 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx);
/* OSSL_PROVIDER * is only used to get the library context */
const char *evp_first_name(OSSL_PROVIDER *prov, int name_id);
int evp_is_a(OSSL_PROVIDER *prov, int number, const char *name);
void evp_doall_names(OSSL_PROVIDER *prov, int number,
void (*fn)(const char *name, void *data),
void *data);