SOL_API struct sol_message_digest * sol_message_digest_new(const struct sol_message_digest_config *config) { const struct sol_message_digest_info *dinfo; struct sol_message_digest *handle; struct sol_message_digest_common_new_params params; struct sol_str_slice algorithm; errno = EINVAL; SOL_NULL_CHECK(config, NULL); SOL_NULL_CHECK(config->on_digest_ready, NULL); SOL_NULL_CHECK(config->algorithm, NULL); #ifndef SOL_NO_API_VERSION if (config->api_version != SOL_MESSAGE_DIGEST_CONFIG_API_VERSION) { SOL_WRN("sol_message_digest_config->api_version=%" PRIu16 ", " "expected version is %" PRIu16 ".", config->api_version, SOL_MESSAGE_DIGEST_CONFIG_API_VERSION); return NULL; } #endif algorithm = sol_str_slice_from_str(config->algorithm); if (!sol_str_table_ptr_lookup(_available_digests, algorithm, &dinfo)) { SOL_WRN("failed to get digest algorithm \"%s\".", config->algorithm); return NULL; } params.config = config; params.ops = &dinfo->ops; params.context_size = dinfo->context_size; params.digest_size = dinfo->digest_size; params.context_template = NULL; handle = sol_message_digest_common_new(params); SOL_NULL_CHECK(handle, NULL); dinfo->init(handle); return handle; }
SOL_API struct sol_message_digest * sol_message_digest_new(const struct sol_message_digest_config *config) { int (*init_fn)(struct sol_message_digest *, const EVP_MD *, const struct sol_str_slice); struct sol_message_digest_common_new_params params; const EVP_MD *md; struct sol_message_digest *handle; int errno_bkp; errno = EINVAL; SOL_NULL_CHECK(config, NULL); SOL_NULL_CHECK(config->on_digest_ready, NULL); SOL_NULL_CHECK(config->algorithm, NULL); #ifndef SOL_NO_API_VERSION if (config->api_version != SOL_MESSAGE_DIGEST_CONFIG_API_VERSION) { SOL_WRN("sol_message_digest_config->api_version=%" PRIu16 ", " "expected version is %" PRIu16 ".", config->api_version, SOL_MESSAGE_DIGEST_CONFIG_API_VERSION); return NULL; } #endif if (!did_openssl_load_digests) { OpenSSL_add_all_digests(); did_openssl_load_digests = true; } params.config = config; params.ops = NULL; md = EVP_get_digestbyname(config->algorithm); if (md) { params.context_handle = EVP_MD_CTX_new(); params.context_free = (void (*)(void *))EVP_MD_CTX_free; init_fn = _sol_message_digest_evp_init; params.ops = &_sol_message_digest_evp_ops; SOL_DBG("using evp, md=%p, algorithm=\"%s\"", md, config->algorithm); } else if (streqn(config->algorithm, "hmac(", strlen("hmac("))) { const char *p = config->algorithm + strlen("hmac("); size_t len = strlen(p); params.context_handle = HMAC_CTX_new(); params.context_free = (void (*)(void *))HMAC_CTX_free; if (len > 1 && p[len - 1] == ')') { char *mdname = strndupa(p, len - 1); md = EVP_get_digestbyname(mdname); if (!md) { SOL_WRN("failed to get digest algorithm \"%s\" for \"%s\".", mdname, config->algorithm); return NULL; } init_fn = _sol_message_digest_hmac_init; params.ops = &_sol_message_digest_hmac_ops; SOL_DBG("using hmac, md=%p, algorithm=\"%s\"", md, mdname); } } if (!params.ops) { SOL_WRN("failed to get digest algorithm \"%s\".", config->algorithm); return NULL; } params.digest_size = EVP_MD_size(md); handle = sol_message_digest_common_new(params); SOL_NULL_CHECK(handle, NULL); errno = init_fn(handle, md, config->key); if (errno) goto error; return handle; error: errno_bkp = errno; sol_message_digest_del(handle); errno = errno_bkp; return NULL; }