/*
* 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_locl.h"
#if !defined(FIPS_MODE)
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
int ret;
const EVP_CIPHER *cipher = c->cipher;
if (cipher->prov != NULL) {
/*
* The cipher has come from a provider and won't have the default flags.
* Find the implicit form so we can check the flags.
* TODO(3.0): This won't work for 3rd party ciphers we know nothing about
* We'll need to think of something else for those.
*/
cipher = EVP_get_cipherbynid(cipher->nid);
if (cipher == NULL) {
EVPerr(EVP_F_EVP_CIPHER_PARAM_TO_ASN1, ASN1_R_UNSUPPORTED_CIPHER);
return -1;
}
}
if (cipher->set_asn1_parameters != NULL)
ret = cipher->set_asn1_parameters(c, type);
else if (cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
switch (EVP_CIPHER_mode(cipher)) {
case EVP_CIPH_WRAP_MODE:
if (EVP_CIPHER_nid(cipher) == NID_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
ret = -1;
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;
const EVP_CIPHER *cipher = c->cipher;
if (cipher->prov != NULL) {
/*
* The cipher has come from a provider and won't have the default flags.
* Find the implicit form so we can check the flags.
*/
cipher = EVP_get_cipherbynid(cipher->nid);
if (cipher == NULL)
return -1;
}
if (cipher->get_asn1_parameters != NULL)
ret = cipher->get_asn1_parameters(c, type);
else if (cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
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);
break;
}
} else
ret = -1;
if (ret == -2)
EVPerr(EVP_F_EVP_CIPHER_ASN1_TO_PARAM, EVP_R_UNSUPPORTED_CIPHER);
else if (ret <= 0)
EVPerr(EVP_F_EVP_CIPHER_ASN1_TO_PARAM, EVP_R_CIPHER_PARAMETER_ERROR);
if (ret < -1)
ret = -1;
return ret;
}
int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *ctx, ASN1_TYPE *type)
{
int i = 0;
unsigned int l;
if (type != NULL) {
unsigned char iv[EVP_MAX_IV_LENGTH];
l = EVP_CIPHER_CTX_iv_length(ctx);
if (!ossl_assert(l <= sizeof(iv)))
return -1;
i = ASN1_TYPE_get_octetstring(type, iv, l);
if (i != (int)l)
return -1;
if (!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1))
return -1;
}
return i;
}
int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
int i = 0;
unsigned int j;
if (type != NULL) {
j = EVP_CIPHER_CTX_iv_length(c);
OPENSSL_assert(j <= sizeof(c->iv));
i = ASN1_TYPE_set_octetstring(type, c->oiv, j);
}
return i;
}
#endif /* !defined(FIPS_MODE) */
/* Convert the various cipher NIDs and dummies to a proper OID NID */
int EVP_CIPHER_type(const EVP_CIPHER *ctx)
{
int nid;
nid = EVP_CIPHER_nid(ctx);
switch (nid) {
case NID_rc2_cbc:
case NID_rc2_64_cbc:
case NID_rc2_40_cbc:
return NID_rc2_cbc;
case NID_rc4:
case NID_rc4_40:
return NID_rc4;
case NID_aes_128_cfb128:
case NID_aes_128_cfb8:
case NID_aes_128_cfb1:
return NID_aes_128_cfb128;