/*
* Copyright 1995-2021 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
*/
/*
* DSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/x509.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/decoder.h>
#include <openssl/encoder.h>
#include "internal/provider.h"
#include "internal/sizes.h"
struct X509_pubkey_st {
X509_ALGOR *algor;
ASN1_BIT_STRING *public_key;
EVP_PKEY *pkey;
/* extra data for the callback, used by d2i_PUBKEY_ex */
OSSL_LIB_CTX *libctx;
char *propq;
/* Flag to force legacy keys */
unsigned int flag_force_legacy : 1;
};
static int x509_pubkey_decode(EVP_PKEY **pk, const X509_PUBKEY *key);
static int x509_pubkey_set0_libctx(X509_PUBKEY *x, OSSL_LIB_CTX *libctx,
const char *propq)
{
if (x != NULL) {
x->libctx = libctx;
OPENSSL_free(x->propq);
x->propq = NULL;
if (propq != NULL) {
x->propq = OPENSSL_strdup(propq);
if (x->propq == NULL)
return 0;
}
}
return 1;
}
ASN1_SEQUENCE(X509_PUBKEY_INTERNAL) = {
ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
} static_ASN1_SEQUENCE_END_name(X509_PUBKEY, X509_PUBKEY_INTERNAL)
static void x509_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
X509_ALGOR_free(pubkey->algor);
ASN1_BIT_STRING_free(pubkey->public_key);
EVP_PKEY_free(pubkey->pkey);
OPENSSL_free(pubkey->propq);
OPENSSL_free(pubkey);
*pval = NULL;
}
static int x509_pubkey_ex_populate(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
return (pubkey->algor != NULL
|| (pubkey->algor = X509_ALGOR_new()) != NULL)
&& (pubkey->public_key != NULL
|| (pubkey->public_key = ASN1_BIT_STRING_new()) != NULL);
}
static int x509_pubkey_ex_new_ex(ASN1_VALUE **pval, const ASN1_ITEM *it,
OSSL_LIB_CTX *libctx, const char *propq)
{
X509_PUBKEY *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL
|| !x509_pubkey_ex_populate((ASN1_VALUE **)&ret, NULL)
|| !x509_pubkey_set0_libctx(ret, libctx, propq)) {
x509_pubkey_ex_free((ASN1_VALUE **)&ret, NULL);
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
} else {
*pval = (ASN1_VALUE *)ret;
}
return ret != NULL;
}
static int x509_pubkey_ex_d2i(ASN1_VALUE **pval,
const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass,
char opt, ASN1_TLC *ctx)
{
const unsigned char *in_saved = *in;
X509_PUBKEY *pubkey;
int ret;
OSSL_DECODER_CTX *dctx = NULL;
if (*pval == NULL && !x509_pubkey_ex_new_ex(pval, it, NULL, NULL))
return 0;
if (!x509_pubkey_ex_populate(pval, NULL)) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
/* This ensures that |*in| advances properly no matter what */
if ((ret = ASN1_item_ex_d2i(pval, in, len,
ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL),
tag, aclass, opt, ctx)) <= 0)
return ret;
pubkey