/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/params.h>
#include <openssl/core_names.h>
#include <openssl/dh.h>
#include "crypto/evp.h"
#include "internal/provider.h"
#include "evp_local.h"
#if !defined(FIPS_MODE)
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
int ret = -1; /* Assume the worst */
const EVP_CIPHER *cipher = c->cipher;
/*
* For legacy implementations, we detect custom AlgorithmIdentifier
* parameter handling by checking if the function pointer
* cipher->set_asn1_parameters is set. We know that this pointer
* is NULL for provided implementations.
*
* Otherwise, for any implementation, we check the flag
* EVP_CIPH_FLAG_CUSTOM_ASN1. If it isn't set, we apply
* default AI parameter extraction.
*
* Otherwise, for provided implementations, we convert |type| to
* a DER encoded blob and pass to the implementation in OSSL_PARAM
* form.
*
* If none of the above applies, this operation is unsupported.
*/
if (cipher->set_asn1_parameters != NULL) {
ret = cipher->set_asn1_parameters(c, type);
} else if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_CUSTOM_ASN1) == 0) {
switch (EVP_CIPHER_mode(cipher)) {
case EVP_CIPH_WRAP_MODE:
if (EVP_CIPHER_is_a(cipher, SN_id_smime_alg_CMS3DESwrap))
ASN1_TYPE_set(type, V_ASN1_NULL, NULL);
ret = 1;
break;
case EVP_CIPH_GCM_MODE:
case EVP_CIPH_CCM_MODE:
case EVP_CIPH_XTS_MODE:
case EVP_CIPH_OCB_MODE:
ret = -2;
break;
default:
ret = EVP_CIPHER_set_asn1_iv(c, type);
}
} else if (cipher->prov != NULL) {
OSSL_PARAM params[3], *p = params;
unsigned char *der = NULL, *derp;
/*
* We make two passes, the first to get the appropriate buffer size,
* and the second to get the actual value.
*/
*p++ = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_ALG_ID,
NULL, 0);
*p = OSSL_PARAM_construct_end();
if (!EVP_CIPHER_CTX_get_params(c, params))
goto err;
/* ... but, we should get a return size too! */
if (params[0].return_size != 0
&& (der = OPENSSL_malloc(params[0].return_size)) != NULL) {
params[0].data = der;
params[0].data_size = params[0].return_size;
params[0].return_size = 0;
derp = der;
if (EVP_CIPHER_CTX_get_params(c, params)
&& d2i_ASN1_TYPE(&type, (const unsigned char **)&derp,
params[0].return_size) != NULL) {
ret = 1;
}
OPENSSL_free(der);
}
} else {
ret = -2;
}
err:
if (ret == -2)
EVPerr(EVP_F_EVP_CIPHER_PARAM_TO_ASN1, ASN1_R_UNSUPPORTED_CIPHER);
else if (ret <= 0)
EVPerr(EVP_F_EVP_CIPHER_PARAM_TO_ASN1, EVP_R_CIPHER_PARAMETER_ERROR);
if (ret < -1)
ret = -1;
return ret;
}
int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
int ret = -1; /* Assume the worst */
const EVP_CIPHER *cipher = c->cipher;
/*
* For legacy implementations, we detect custom AlgorithmIdentifier
* parameter handling by checking if there the function pointer
* cipher->get_asn1_parameters is set. We know that this pointer
* is NULL for provided implementations.
*
* Otherwise, for any implementation, we check the flag
* EVP_CIPH_FLAG_CUSTOM_ASN1. If it isn't set, we apply
* default AI parameter creation.
*
* Otherwise, for provided implementations, we get the AI parameter
* in DER encoded form from the implementation by requesting the
* appropriate OSSL_PARAM and converting the result to a ASN1_TYPE.
*
* If none of the above applies, this operation is unsupported.
*/
if (cipher->get_asn1_parameters != NULL) {
ret = cipher->get_asn1_parameters(c, type);
} else if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_CUSTOM_ASN1) == 0) {
switch (EVP_CIPHER_mode(cipher)) {
case EVP_CIPH_WRAP_MODE:
ret = 1;
break;
case EVP_CIPH_GCM_MODE:
case EVP_CIPH_CCM_MODE:
case EVP_CIPH_XTS_MODE:
case EVP_CIPH_OCB_MODE:
ret = -2;
break;
default:
ret = EVP_CIPHER_get_asn1_iv(c, type);
}
} else if (cipher->prov != NULL) {
OSSL_PARAM params[3], *p = params;
unsigned