1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * DSA low level APIs are deprecated for public use, but still ok for
12e1051a39Sopenharmony_ci * internal use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <stdio.h>
17e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
18e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
19e1051a39Sopenharmony_ci#include <openssl/x509.h>
20e1051a39Sopenharmony_ci#include <openssl/engine.h>
21e1051a39Sopenharmony_ci#include "crypto/asn1.h"
22e1051a39Sopenharmony_ci#include "crypto/evp.h"
23e1051a39Sopenharmony_ci#include "crypto/x509.h"
24e1051a39Sopenharmony_ci#include <openssl/rsa.h>
25e1051a39Sopenharmony_ci#include <openssl/dsa.h>
26e1051a39Sopenharmony_ci#include <openssl/decoder.h>
27e1051a39Sopenharmony_ci#include <openssl/encoder.h>
28e1051a39Sopenharmony_ci#include "internal/provider.h"
29e1051a39Sopenharmony_ci#include "internal/sizes.h"
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_cistruct X509_pubkey_st {
32e1051a39Sopenharmony_ci    X509_ALGOR *algor;
33e1051a39Sopenharmony_ci    ASN1_BIT_STRING *public_key;
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_ci    /* extra data for the callback, used by d2i_PUBKEY_ex */
38e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx;
39e1051a39Sopenharmony_ci    char *propq;
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_ci    /* Flag to force legacy keys */
42e1051a39Sopenharmony_ci    unsigned int flag_force_legacy : 1;
43e1051a39Sopenharmony_ci};
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_cistatic int x509_pubkey_decode(EVP_PKEY **pk, const X509_PUBKEY *key);
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_cistatic int x509_pubkey_set0_libctx(X509_PUBKEY *x, OSSL_LIB_CTX *libctx,
48e1051a39Sopenharmony_ci                                   const char *propq)
49e1051a39Sopenharmony_ci{
50e1051a39Sopenharmony_ci    if (x != NULL) {
51e1051a39Sopenharmony_ci        x->libctx = libctx;
52e1051a39Sopenharmony_ci        OPENSSL_free(x->propq);
53e1051a39Sopenharmony_ci        x->propq = NULL;
54e1051a39Sopenharmony_ci        if (propq != NULL) {
55e1051a39Sopenharmony_ci            x->propq = OPENSSL_strdup(propq);
56e1051a39Sopenharmony_ci            if (x->propq == NULL)
57e1051a39Sopenharmony_ci                return 0;
58e1051a39Sopenharmony_ci        }
59e1051a39Sopenharmony_ci    }
60e1051a39Sopenharmony_ci    return 1;
61e1051a39Sopenharmony_ci}
62e1051a39Sopenharmony_ci
63e1051a39Sopenharmony_ciASN1_SEQUENCE(X509_PUBKEY_INTERNAL) = {
64e1051a39Sopenharmony_ci        ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
65e1051a39Sopenharmony_ci        ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
66e1051a39Sopenharmony_ci} static_ASN1_SEQUENCE_END_name(X509_PUBKEY, X509_PUBKEY_INTERNAL)
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ciX509_PUBKEY *ossl_d2i_X509_PUBKEY_INTERNAL(const unsigned char **pp,
69e1051a39Sopenharmony_ci                                           long len, OSSL_LIB_CTX *libctx)
70e1051a39Sopenharmony_ci{
71e1051a39Sopenharmony_ci    X509_PUBKEY *xpub = OPENSSL_zalloc(sizeof(*xpub));
72e1051a39Sopenharmony_ci
73e1051a39Sopenharmony_ci    if (xpub == NULL)
74e1051a39Sopenharmony_ci        return NULL;
75e1051a39Sopenharmony_ci    return (X509_PUBKEY *)ASN1_item_d2i_ex((ASN1_VALUE **)&xpub, pp, len,
76e1051a39Sopenharmony_ci                                           ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL),
77e1051a39Sopenharmony_ci                                           libctx, NULL);
78e1051a39Sopenharmony_ci}
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_civoid ossl_X509_PUBKEY_INTERNAL_free(X509_PUBKEY *xpub)
81e1051a39Sopenharmony_ci{
82e1051a39Sopenharmony_ci    ASN1_item_free((ASN1_VALUE *)xpub, ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL));
83e1051a39Sopenharmony_ci}
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_cistatic void x509_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
86e1051a39Sopenharmony_ci{
87e1051a39Sopenharmony_ci    X509_PUBKEY *pubkey;
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci    if (pval != NULL && (pubkey = (X509_PUBKEY *)*pval) != NULL) {
90e1051a39Sopenharmony_ci        X509_ALGOR_free(pubkey->algor);
91e1051a39Sopenharmony_ci        ASN1_BIT_STRING_free(pubkey->public_key);
92e1051a39Sopenharmony_ci        EVP_PKEY_free(pubkey->pkey);
93e1051a39Sopenharmony_ci        OPENSSL_free(pubkey->propq);
94e1051a39Sopenharmony_ci        OPENSSL_free(pubkey);
95e1051a39Sopenharmony_ci        *pval = NULL;
96e1051a39Sopenharmony_ci    }
97e1051a39Sopenharmony_ci}
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_cistatic int x509_pubkey_ex_populate(ASN1_VALUE **pval, const ASN1_ITEM *it)
100e1051a39Sopenharmony_ci{
101e1051a39Sopenharmony_ci    X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
102e1051a39Sopenharmony_ci
103e1051a39Sopenharmony_ci    return (pubkey->algor != NULL
104e1051a39Sopenharmony_ci            || (pubkey->algor = X509_ALGOR_new()) != NULL)
105e1051a39Sopenharmony_ci        && (pubkey->public_key != NULL
106e1051a39Sopenharmony_ci            || (pubkey->public_key = ASN1_BIT_STRING_new()) != NULL);
107e1051a39Sopenharmony_ci}
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_cistatic int x509_pubkey_ex_new_ex(ASN1_VALUE **pval, const ASN1_ITEM *it,
111e1051a39Sopenharmony_ci                                 OSSL_LIB_CTX *libctx, const char *propq)
112e1051a39Sopenharmony_ci{
113e1051a39Sopenharmony_ci    X509_PUBKEY *ret;
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci    if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL
116e1051a39Sopenharmony_ci        || !x509_pubkey_ex_populate((ASN1_VALUE **)&ret, NULL)
117e1051a39Sopenharmony_ci        || !x509_pubkey_set0_libctx(ret, libctx, propq)) {
118e1051a39Sopenharmony_ci        x509_pubkey_ex_free((ASN1_VALUE **)&ret, NULL);
119e1051a39Sopenharmony_ci        ret = NULL;
120e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
121e1051a39Sopenharmony_ci    } else {
122e1051a39Sopenharmony_ci        *pval = (ASN1_VALUE *)ret;
123e1051a39Sopenharmony_ci    }
124e1051a39Sopenharmony_ci
125e1051a39Sopenharmony_ci    return ret != NULL;
126e1051a39Sopenharmony_ci}
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_cistatic int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval,
129e1051a39Sopenharmony_ci                                 const unsigned char **in, long len,
130e1051a39Sopenharmony_ci                                 const ASN1_ITEM *it, int tag, int aclass,
131e1051a39Sopenharmony_ci                                 char opt, ASN1_TLC *ctx, OSSL_LIB_CTX *libctx,
132e1051a39Sopenharmony_ci                                 const char *propq)
133e1051a39Sopenharmony_ci{
134e1051a39Sopenharmony_ci    const unsigned char *in_saved = *in;
135e1051a39Sopenharmony_ci    size_t publen;
136e1051a39Sopenharmony_ci    X509_PUBKEY *pubkey;
137e1051a39Sopenharmony_ci    int ret;
138e1051a39Sopenharmony_ci    OSSL_DECODER_CTX *dctx = NULL;
139e1051a39Sopenharmony_ci    unsigned char *tmpbuf = NULL;
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci    if (*pval == NULL && !x509_pubkey_ex_new_ex(pval, it, libctx, propq))
142e1051a39Sopenharmony_ci        return 0;
143e1051a39Sopenharmony_ci    if (!x509_pubkey_ex_populate(pval, NULL)) {
144e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
145e1051a39Sopenharmony_ci        return 0;
146e1051a39Sopenharmony_ci    }
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ci    /* This ensures that |*in| advances properly no matter what */
149e1051a39Sopenharmony_ci    if ((ret = ASN1_item_ex_d2i(pval, in, len,
150e1051a39Sopenharmony_ci                                ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL),
151e1051a39Sopenharmony_ci                                tag, aclass, opt, ctx)) <= 0)
152e1051a39Sopenharmony_ci        return ret;
153e1051a39Sopenharmony_ci
154e1051a39Sopenharmony_ci    publen = *in - in_saved;
155e1051a39Sopenharmony_ci    if (!ossl_assert(publen > 0)) {
156e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
157e1051a39Sopenharmony_ci        return 0;
158e1051a39Sopenharmony_ci    }
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci    pubkey = (X509_PUBKEY *)*pval;
161e1051a39Sopenharmony_ci    EVP_PKEY_free(pubkey->pkey);
162e1051a39Sopenharmony_ci    pubkey->pkey = NULL;
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_ci    /*
165e1051a39Sopenharmony_ci     * Opportunistically decode the key but remove any non fatal errors
166e1051a39Sopenharmony_ci     * from the queue. Subsequent explicit attempts to decode/use the key
167e1051a39Sopenharmony_ci     * will return an appropriate error.
168e1051a39Sopenharmony_ci     */
169e1051a39Sopenharmony_ci    ERR_set_mark();
170e1051a39Sopenharmony_ci
171e1051a39Sopenharmony_ci    /*
172e1051a39Sopenharmony_ci     * Try to decode with legacy method first.  This ensures that engines
173e1051a39Sopenharmony_ci     * aren't overriden by providers.
174e1051a39Sopenharmony_ci     */
175e1051a39Sopenharmony_ci    if ((ret = x509_pubkey_decode(&pubkey->pkey, pubkey)) == -1) {
176e1051a39Sopenharmony_ci        /* -1 indicates a fatal error, like malloc failure */
177e1051a39Sopenharmony_ci        ERR_clear_last_mark();
178e1051a39Sopenharmony_ci        goto end;
179e1051a39Sopenharmony_ci    }
180e1051a39Sopenharmony_ci
181e1051a39Sopenharmony_ci    /* Try to decode it into an EVP_PKEY with OSSL_DECODER */
182e1051a39Sopenharmony_ci    if (ret <= 0 && !pubkey->flag_force_legacy) {
183e1051a39Sopenharmony_ci        const unsigned char *p;
184e1051a39Sopenharmony_ci        char txtoidname[OSSL_MAX_NAME_SIZE];
185e1051a39Sopenharmony_ci        size_t slen = publen;
186e1051a39Sopenharmony_ci
187e1051a39Sopenharmony_ci        /*
188e1051a39Sopenharmony_ci        * The decoders don't know how to handle anything other than Universal
189e1051a39Sopenharmony_ci        * class so we modify the data accordingly.
190e1051a39Sopenharmony_ci        */
191e1051a39Sopenharmony_ci        if (aclass != V_ASN1_UNIVERSAL) {
192e1051a39Sopenharmony_ci            tmpbuf = OPENSSL_memdup(in_saved, publen);
193e1051a39Sopenharmony_ci            if (tmpbuf == NULL) {
194e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
195e1051a39Sopenharmony_ci                return 0;
196e1051a39Sopenharmony_ci            }
197e1051a39Sopenharmony_ci            in_saved = tmpbuf;
198e1051a39Sopenharmony_ci            *tmpbuf = V_ASN1_CONSTRUCTED | V_ASN1_SEQUENCE;
199e1051a39Sopenharmony_ci        }
200e1051a39Sopenharmony_ci        p = in_saved;
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ci        if (OBJ_obj2txt(txtoidname, sizeof(txtoidname),
203e1051a39Sopenharmony_ci                        pubkey->algor->algorithm, 0) <= 0) {
204e1051a39Sopenharmony_ci            ERR_clear_last_mark();
205e1051a39Sopenharmony_ci            goto end;
206e1051a39Sopenharmony_ci        }
207e1051a39Sopenharmony_ci        if ((dctx =
208e1051a39Sopenharmony_ci             OSSL_DECODER_CTX_new_for_pkey(&pubkey->pkey,
209e1051a39Sopenharmony_ci                                           "DER", "SubjectPublicKeyInfo",
210e1051a39Sopenharmony_ci                                           txtoidname, EVP_PKEY_PUBLIC_KEY,
211e1051a39Sopenharmony_ci                                           pubkey->libctx,
212e1051a39Sopenharmony_ci                                           pubkey->propq)) != NULL)
213e1051a39Sopenharmony_ci            /*
214e1051a39Sopenharmony_ci             * As said higher up, we're being opportunistic.  In other words,
215e1051a39Sopenharmony_ci             * we don't care if we fail.
216e1051a39Sopenharmony_ci             */
217e1051a39Sopenharmony_ci            if (OSSL_DECODER_from_data(dctx, &p, &slen)) {
218e1051a39Sopenharmony_ci                if (slen != 0) {
219e1051a39Sopenharmony_ci                    /*
220e1051a39Sopenharmony_ci                     * If we successfully decoded then we *must* consume all the
221e1051a39Sopenharmony_ci                     * bytes.
222e1051a39Sopenharmony_ci                     */
223e1051a39Sopenharmony_ci                    ERR_clear_last_mark();
224e1051a39Sopenharmony_ci                    ERR_raise(ERR_LIB_ASN1, EVP_R_DECODE_ERROR);
225e1051a39Sopenharmony_ci                    goto end;
226e1051a39Sopenharmony_ci                }
227e1051a39Sopenharmony_ci            }
228e1051a39Sopenharmony_ci    }
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci    ERR_pop_to_mark();
231e1051a39Sopenharmony_ci    ret = 1;
232e1051a39Sopenharmony_ci end:
233e1051a39Sopenharmony_ci    OSSL_DECODER_CTX_free(dctx);
234e1051a39Sopenharmony_ci    OPENSSL_free(tmpbuf);
235e1051a39Sopenharmony_ci    return ret;
236e1051a39Sopenharmony_ci}
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_cistatic int x509_pubkey_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
239e1051a39Sopenharmony_ci                              const ASN1_ITEM *it, int tag, int aclass)
240e1051a39Sopenharmony_ci{
241e1051a39Sopenharmony_ci    return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL),
242e1051a39Sopenharmony_ci                            tag, aclass);
243e1051a39Sopenharmony_ci}
244e1051a39Sopenharmony_ci
245e1051a39Sopenharmony_cistatic int x509_pubkey_ex_print(BIO *out, const ASN1_VALUE **pval, int indent,
246e1051a39Sopenharmony_ci                                const char *fname, const ASN1_PCTX *pctx)
247e1051a39Sopenharmony_ci{
248e1051a39Sopenharmony_ci    return ASN1_item_print(out, *pval, indent,
249e1051a39Sopenharmony_ci                           ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL), pctx);
250e1051a39Sopenharmony_ci}
251e1051a39Sopenharmony_ci
252e1051a39Sopenharmony_cistatic const ASN1_EXTERN_FUNCS x509_pubkey_ff = {
253e1051a39Sopenharmony_ci    NULL,
254e1051a39Sopenharmony_ci    NULL,
255e1051a39Sopenharmony_ci    x509_pubkey_ex_free,
256e1051a39Sopenharmony_ci    0,                          /* Default clear behaviour is OK */
257e1051a39Sopenharmony_ci    NULL,
258e1051a39Sopenharmony_ci    x509_pubkey_ex_i2d,
259e1051a39Sopenharmony_ci    x509_pubkey_ex_print,
260e1051a39Sopenharmony_ci    x509_pubkey_ex_new_ex,
261e1051a39Sopenharmony_ci    x509_pubkey_ex_d2i_ex,
262e1051a39Sopenharmony_ci};
263e1051a39Sopenharmony_ci
264e1051a39Sopenharmony_ciIMPLEMENT_EXTERN_ASN1(X509_PUBKEY, V_ASN1_SEQUENCE, x509_pubkey_ff)
265e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
266e1051a39Sopenharmony_ci
267e1051a39Sopenharmony_ciX509_PUBKEY *X509_PUBKEY_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
268e1051a39Sopenharmony_ci{
269e1051a39Sopenharmony_ci    X509_PUBKEY *pubkey = NULL;
270e1051a39Sopenharmony_ci
271e1051a39Sopenharmony_ci    pubkey = (X509_PUBKEY *)ASN1_item_new_ex(X509_PUBKEY_it(), libctx, propq);
272e1051a39Sopenharmony_ci    if (!x509_pubkey_set0_libctx(pubkey, libctx, propq)) {
273e1051a39Sopenharmony_ci        X509_PUBKEY_free(pubkey);
274e1051a39Sopenharmony_ci        pubkey = NULL;
275e1051a39Sopenharmony_ci    }
276e1051a39Sopenharmony_ci    return pubkey;
277e1051a39Sopenharmony_ci}
278e1051a39Sopenharmony_ci
279e1051a39Sopenharmony_ci/*
280e1051a39Sopenharmony_ci * X509_PUBKEY_dup() must be implemented manually, because there is no
281e1051a39Sopenharmony_ci * support for it in ASN1_EXTERN_FUNCS.
282e1051a39Sopenharmony_ci */
283e1051a39Sopenharmony_ciX509_PUBKEY *X509_PUBKEY_dup(const X509_PUBKEY *a)
284e1051a39Sopenharmony_ci{
285e1051a39Sopenharmony_ci    X509_PUBKEY *pubkey = OPENSSL_zalloc(sizeof(*pubkey));
286e1051a39Sopenharmony_ci
287e1051a39Sopenharmony_ci    if (pubkey == NULL
288e1051a39Sopenharmony_ci            || !x509_pubkey_set0_libctx(pubkey, a->libctx, a->propq)
289e1051a39Sopenharmony_ci            || (pubkey->algor = X509_ALGOR_dup(a->algor)) == NULL
290e1051a39Sopenharmony_ci            || (pubkey->public_key = ASN1_BIT_STRING_new()) == NULL
291e1051a39Sopenharmony_ci            || !ASN1_BIT_STRING_set(pubkey->public_key,
292e1051a39Sopenharmony_ci                                    a->public_key->data,
293e1051a39Sopenharmony_ci                                    a->public_key->length)) {
294e1051a39Sopenharmony_ci        x509_pubkey_ex_free((ASN1_VALUE **)&pubkey,
295e1051a39Sopenharmony_ci                            ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL));
296e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
297e1051a39Sopenharmony_ci        return NULL;
298e1051a39Sopenharmony_ci    }
299e1051a39Sopenharmony_ci
300e1051a39Sopenharmony_ci    if (a->pkey != NULL) {
301e1051a39Sopenharmony_ci        ERR_set_mark();
302e1051a39Sopenharmony_ci        pubkey->pkey = EVP_PKEY_dup(a->pkey);
303e1051a39Sopenharmony_ci        if (pubkey->pkey == NULL) {
304e1051a39Sopenharmony_ci            pubkey->flag_force_legacy = 1;
305e1051a39Sopenharmony_ci            if (x509_pubkey_decode(&pubkey->pkey, pubkey) <= 0) {
306e1051a39Sopenharmony_ci                x509_pubkey_ex_free((ASN1_VALUE **)&pubkey,
307e1051a39Sopenharmony_ci                                    ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL));
308e1051a39Sopenharmony_ci                ERR_clear_last_mark();
309e1051a39Sopenharmony_ci                return NULL;
310e1051a39Sopenharmony_ci            }
311e1051a39Sopenharmony_ci        }
312e1051a39Sopenharmony_ci        ERR_pop_to_mark();
313e1051a39Sopenharmony_ci    }
314e1051a39Sopenharmony_ci    return pubkey;
315e1051a39Sopenharmony_ci}
316e1051a39Sopenharmony_ci
317e1051a39Sopenharmony_ciint X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
318e1051a39Sopenharmony_ci{
319e1051a39Sopenharmony_ci    X509_PUBKEY *pk = NULL;
320e1051a39Sopenharmony_ci
321e1051a39Sopenharmony_ci    if (x == NULL || pkey == NULL) {
322e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
323e1051a39Sopenharmony_ci        return 0;
324e1051a39Sopenharmony_ci    }
325e1051a39Sopenharmony_ci
326e1051a39Sopenharmony_ci    if (pkey->ameth != NULL) {
327e1051a39Sopenharmony_ci        if ((pk = X509_PUBKEY_new()) == NULL) {
328e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
329e1051a39Sopenharmony_ci            goto error;
330e1051a39Sopenharmony_ci        }
331e1051a39Sopenharmony_ci        if (pkey->ameth->pub_encode != NULL) {
332e1051a39Sopenharmony_ci            if (!pkey->ameth->pub_encode(pk, pkey)) {
333e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
334e1051a39Sopenharmony_ci                goto error;
335e1051a39Sopenharmony_ci            }
336e1051a39Sopenharmony_ci        } else {
337e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED);
338e1051a39Sopenharmony_ci            goto error;
339e1051a39Sopenharmony_ci        }
340e1051a39Sopenharmony_ci    } else if (evp_pkey_is_provided(pkey)) {
341e1051a39Sopenharmony_ci        unsigned char *der = NULL;
342e1051a39Sopenharmony_ci        size_t derlen = 0;
343e1051a39Sopenharmony_ci        OSSL_ENCODER_CTX *ectx =
344e1051a39Sopenharmony_ci            OSSL_ENCODER_CTX_new_for_pkey(pkey, EVP_PKEY_PUBLIC_KEY,
345e1051a39Sopenharmony_ci                                          "DER", "SubjectPublicKeyInfo",
346e1051a39Sopenharmony_ci                                          NULL);
347e1051a39Sopenharmony_ci
348e1051a39Sopenharmony_ci        if (OSSL_ENCODER_to_data(ectx, &der, &derlen)) {
349e1051a39Sopenharmony_ci            const unsigned char *pder = der;
350e1051a39Sopenharmony_ci
351e1051a39Sopenharmony_ci            pk = d2i_X509_PUBKEY(NULL, &pder, (long)derlen);
352e1051a39Sopenharmony_ci        }
353e1051a39Sopenharmony_ci
354e1051a39Sopenharmony_ci        OSSL_ENCODER_CTX_free(ectx);
355e1051a39Sopenharmony_ci        OPENSSL_free(der);
356e1051a39Sopenharmony_ci    }
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_ci    if (pk == NULL) {
359e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
360e1051a39Sopenharmony_ci        goto error;
361e1051a39Sopenharmony_ci    }
362e1051a39Sopenharmony_ci
363e1051a39Sopenharmony_ci    X509_PUBKEY_free(*x);
364e1051a39Sopenharmony_ci    if (!EVP_PKEY_up_ref(pkey)) {
365e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
366e1051a39Sopenharmony_ci        goto error;
367e1051a39Sopenharmony_ci    }
368e1051a39Sopenharmony_ci    *x = pk;
369e1051a39Sopenharmony_ci
370e1051a39Sopenharmony_ci    /*
371e1051a39Sopenharmony_ci     * pk->pkey is NULL when using the legacy routine, but is non-NULL when
372e1051a39Sopenharmony_ci     * going through the encoder, and for all intents and purposes, it's
373e1051a39Sopenharmony_ci     * a perfect copy of the public key portions of |pkey|, just not the same
374e1051a39Sopenharmony_ci     * instance.  If that's all there was to pkey then we could simply return
375e1051a39Sopenharmony_ci     * early, right here. However, some application might very well depend on
376e1051a39Sopenharmony_ci     * the passed |pkey| being used and none other, so we spend a few more
377e1051a39Sopenharmony_ci     * cycles throwing away the newly created |pk->pkey| and replace it with
378e1051a39Sopenharmony_ci     * |pkey|.
379e1051a39Sopenharmony_ci     */
380e1051a39Sopenharmony_ci    if (pk->pkey != NULL)
381e1051a39Sopenharmony_ci        EVP_PKEY_free(pk->pkey);
382e1051a39Sopenharmony_ci
383e1051a39Sopenharmony_ci    pk->pkey = pkey;
384e1051a39Sopenharmony_ci    return 1;
385e1051a39Sopenharmony_ci
386e1051a39Sopenharmony_ci error:
387e1051a39Sopenharmony_ci    X509_PUBKEY_free(pk);
388e1051a39Sopenharmony_ci    return 0;
389e1051a39Sopenharmony_ci}
390e1051a39Sopenharmony_ci
391e1051a39Sopenharmony_ci/*
392e1051a39Sopenharmony_ci * Attempt to decode a public key.
393e1051a39Sopenharmony_ci * Returns 1 on success, 0 for a decode failure and -1 for a fatal
394e1051a39Sopenharmony_ci * error e.g. malloc failure.
395e1051a39Sopenharmony_ci *
396e1051a39Sopenharmony_ci * This function is #legacy.
397e1051a39Sopenharmony_ci */
398e1051a39Sopenharmony_cistatic int x509_pubkey_decode(EVP_PKEY **ppkey, const X509_PUBKEY *key)
399e1051a39Sopenharmony_ci{
400e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
401e1051a39Sopenharmony_ci    int nid;
402e1051a39Sopenharmony_ci
403e1051a39Sopenharmony_ci    nid = OBJ_obj2nid(key->algor->algorithm);
404e1051a39Sopenharmony_ci    if (!key->flag_force_legacy) {
405e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
406e1051a39Sopenharmony_ci        ENGINE *e = NULL;
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci        e = ENGINE_get_pkey_meth_engine(nid);
409e1051a39Sopenharmony_ci        if (e == NULL)
410e1051a39Sopenharmony_ci            return 0;
411e1051a39Sopenharmony_ci        ENGINE_finish(e);
412e1051a39Sopenharmony_ci#else
413e1051a39Sopenharmony_ci        return 0;
414e1051a39Sopenharmony_ci#endif
415e1051a39Sopenharmony_ci    }
416e1051a39Sopenharmony_ci
417e1051a39Sopenharmony_ci    pkey = EVP_PKEY_new();
418e1051a39Sopenharmony_ci    if (pkey == NULL) {
419e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
420e1051a39Sopenharmony_ci        return -1;
421e1051a39Sopenharmony_ci    }
422e1051a39Sopenharmony_ci
423e1051a39Sopenharmony_ci    if (!EVP_PKEY_set_type(pkey, nid)) {
424e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
425e1051a39Sopenharmony_ci        goto error;
426e1051a39Sopenharmony_ci    }
427e1051a39Sopenharmony_ci
428e1051a39Sopenharmony_ci    if (pkey->ameth->pub_decode) {
429e1051a39Sopenharmony_ci        /*
430e1051a39Sopenharmony_ci         * Treat any failure of pub_decode as a decode error. In
431e1051a39Sopenharmony_ci         * future we could have different return codes for decode
432e1051a39Sopenharmony_ci         * errors and fatal errors such as malloc failure.
433e1051a39Sopenharmony_ci         */
434e1051a39Sopenharmony_ci        if (!pkey->ameth->pub_decode(pkey, key))
435e1051a39Sopenharmony_ci            goto error;
436e1051a39Sopenharmony_ci    } else {
437e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED);
438e1051a39Sopenharmony_ci        goto error;
439e1051a39Sopenharmony_ci    }
440e1051a39Sopenharmony_ci
441e1051a39Sopenharmony_ci    *ppkey = pkey;
442e1051a39Sopenharmony_ci    return 1;
443e1051a39Sopenharmony_ci
444e1051a39Sopenharmony_ci error:
445e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
446e1051a39Sopenharmony_ci    return 0;
447e1051a39Sopenharmony_ci}
448e1051a39Sopenharmony_ci
449e1051a39Sopenharmony_ciEVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key)
450e1051a39Sopenharmony_ci{
451e1051a39Sopenharmony_ci    if (key == NULL) {
452e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
453e1051a39Sopenharmony_ci        return NULL;
454e1051a39Sopenharmony_ci    }
455e1051a39Sopenharmony_ci
456e1051a39Sopenharmony_ci    if (key->pkey == NULL) {
457e1051a39Sopenharmony_ci        /* We failed to decode the key when we loaded it, or it was never set */
458e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
459e1051a39Sopenharmony_ci        return NULL;
460e1051a39Sopenharmony_ci    }
461e1051a39Sopenharmony_ci
462e1051a39Sopenharmony_ci    return key->pkey;
463e1051a39Sopenharmony_ci}
464e1051a39Sopenharmony_ci
465e1051a39Sopenharmony_ciEVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key)
466e1051a39Sopenharmony_ci{
467e1051a39Sopenharmony_ci    EVP_PKEY *ret = X509_PUBKEY_get0(key);
468e1051a39Sopenharmony_ci
469e1051a39Sopenharmony_ci    if (ret != NULL && !EVP_PKEY_up_ref(ret)) {
470e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
471e1051a39Sopenharmony_ci        ret = NULL;
472e1051a39Sopenharmony_ci    }
473e1051a39Sopenharmony_ci    return ret;
474e1051a39Sopenharmony_ci}
475e1051a39Sopenharmony_ci
476e1051a39Sopenharmony_ci/*
477e1051a39Sopenharmony_ci * Now three pseudo ASN1 routines that take an EVP_PKEY structure and encode
478e1051a39Sopenharmony_ci * or decode as X509_PUBKEY
479e1051a39Sopenharmony_ci */
480e1051a39Sopenharmony_cistatic EVP_PKEY *d2i_PUBKEY_int(EVP_PKEY **a,
481e1051a39Sopenharmony_ci                                const unsigned char **pp, long length,
482e1051a39Sopenharmony_ci                                OSSL_LIB_CTX *libctx, const char *propq,
483e1051a39Sopenharmony_ci                                unsigned int force_legacy,
484e1051a39Sopenharmony_ci                                X509_PUBKEY *
485e1051a39Sopenharmony_ci                                (*d2i_x509_pubkey)(X509_PUBKEY **a,
486e1051a39Sopenharmony_ci                                                   const unsigned char **in,
487e1051a39Sopenharmony_ci                                                   long len))
488e1051a39Sopenharmony_ci{
489e1051a39Sopenharmony_ci    X509_PUBKEY *xpk, *xpk2 = NULL, **pxpk = NULL;
490e1051a39Sopenharmony_ci    EVP_PKEY *pktmp = NULL;
491e1051a39Sopenharmony_ci    const unsigned char *q;
492e1051a39Sopenharmony_ci
493e1051a39Sopenharmony_ci    q = *pp;
494e1051a39Sopenharmony_ci
495e1051a39Sopenharmony_ci    /*
496e1051a39Sopenharmony_ci     * If libctx or propq are non-NULL, we take advantage of the reuse
497e1051a39Sopenharmony_ci     * feature.  It's not generally recommended, but is safe enough for
498e1051a39Sopenharmony_ci     * newly created structures.
499e1051a39Sopenharmony_ci     */
500e1051a39Sopenharmony_ci    if (libctx != NULL || propq != NULL || force_legacy) {
501e1051a39Sopenharmony_ci        xpk2 = OPENSSL_zalloc(sizeof(*xpk2));
502e1051a39Sopenharmony_ci        if (xpk2 == NULL) {
503e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
504e1051a39Sopenharmony_ci            return NULL;
505e1051a39Sopenharmony_ci        }
506e1051a39Sopenharmony_ci        if (!x509_pubkey_set0_libctx(xpk2, libctx, propq))
507e1051a39Sopenharmony_ci            goto end;
508e1051a39Sopenharmony_ci        xpk2->flag_force_legacy = !!force_legacy;
509e1051a39Sopenharmony_ci        pxpk = &xpk2;
510e1051a39Sopenharmony_ci    }
511e1051a39Sopenharmony_ci    xpk = d2i_x509_pubkey(pxpk, &q, length);
512e1051a39Sopenharmony_ci    if (xpk == NULL)
513e1051a39Sopenharmony_ci        goto end;
514e1051a39Sopenharmony_ci    pktmp = X509_PUBKEY_get(xpk);
515e1051a39Sopenharmony_ci    X509_PUBKEY_free(xpk);
516e1051a39Sopenharmony_ci    xpk2 = NULL;                 /* We know that xpk == xpk2 */
517e1051a39Sopenharmony_ci    if (pktmp == NULL)
518e1051a39Sopenharmony_ci        goto end;
519e1051a39Sopenharmony_ci    *pp = q;
520e1051a39Sopenharmony_ci    if (a != NULL) {
521e1051a39Sopenharmony_ci        EVP_PKEY_free(*a);
522e1051a39Sopenharmony_ci        *a = pktmp;
523e1051a39Sopenharmony_ci    }
524e1051a39Sopenharmony_ci end:
525e1051a39Sopenharmony_ci    X509_PUBKEY_free(xpk2);
526e1051a39Sopenharmony_ci    return pktmp;
527e1051a39Sopenharmony_ci}
528e1051a39Sopenharmony_ci
529e1051a39Sopenharmony_ci/* For the algorithm specific d2i functions further down */
530e1051a39Sopenharmony_ciEVP_PKEY *ossl_d2i_PUBKEY_legacy(EVP_PKEY **a, const unsigned char **pp,
531e1051a39Sopenharmony_ci                                 long length)
532e1051a39Sopenharmony_ci{
533e1051a39Sopenharmony_ci    return d2i_PUBKEY_int(a, pp, length, NULL, NULL, 1, d2i_X509_PUBKEY);
534e1051a39Sopenharmony_ci}
535e1051a39Sopenharmony_ci
536e1051a39Sopenharmony_ciEVP_PKEY *d2i_PUBKEY_ex(EVP_PKEY **a, const unsigned char **pp, long length,
537e1051a39Sopenharmony_ci                        OSSL_LIB_CTX *libctx, const char *propq)
538e1051a39Sopenharmony_ci{
539e1051a39Sopenharmony_ci    return d2i_PUBKEY_int(a, pp, length, libctx, propq, 0, d2i_X509_PUBKEY);
540e1051a39Sopenharmony_ci}
541e1051a39Sopenharmony_ci
542e1051a39Sopenharmony_ciEVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
543e1051a39Sopenharmony_ci{
544e1051a39Sopenharmony_ci    return d2i_PUBKEY_ex(a, pp, length, NULL, NULL);
545e1051a39Sopenharmony_ci}
546e1051a39Sopenharmony_ci
547e1051a39Sopenharmony_ciint i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
548e1051a39Sopenharmony_ci{
549e1051a39Sopenharmony_ci    int ret = -1;
550e1051a39Sopenharmony_ci
551e1051a39Sopenharmony_ci    if (a == NULL)
552e1051a39Sopenharmony_ci        return 0;
553e1051a39Sopenharmony_ci    if (a->ameth != NULL) {
554e1051a39Sopenharmony_ci        X509_PUBKEY *xpk = NULL;
555e1051a39Sopenharmony_ci
556e1051a39Sopenharmony_ci        if ((xpk = X509_PUBKEY_new()) == NULL)
557e1051a39Sopenharmony_ci            return -1;
558e1051a39Sopenharmony_ci
559e1051a39Sopenharmony_ci        /* pub_encode() only encode parameters, not the key itself */
560e1051a39Sopenharmony_ci        if (a->ameth->pub_encode != NULL && a->ameth->pub_encode(xpk, a)) {
561e1051a39Sopenharmony_ci            xpk->pkey = (EVP_PKEY *)a;
562e1051a39Sopenharmony_ci            ret = i2d_X509_PUBKEY(xpk, pp);
563e1051a39Sopenharmony_ci            xpk->pkey = NULL;
564e1051a39Sopenharmony_ci        }
565e1051a39Sopenharmony_ci        X509_PUBKEY_free(xpk);
566e1051a39Sopenharmony_ci    } else if (a->keymgmt != NULL) {
567e1051a39Sopenharmony_ci        OSSL_ENCODER_CTX *ctx =
568e1051a39Sopenharmony_ci            OSSL_ENCODER_CTX_new_for_pkey(a, EVP_PKEY_PUBLIC_KEY,
569e1051a39Sopenharmony_ci                                          "DER", "SubjectPublicKeyInfo",
570e1051a39Sopenharmony_ci                                          NULL);
571e1051a39Sopenharmony_ci        BIO *out = BIO_new(BIO_s_mem());
572e1051a39Sopenharmony_ci        BUF_MEM *buf = NULL;
573e1051a39Sopenharmony_ci
574e1051a39Sopenharmony_ci        if (OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0
575e1051a39Sopenharmony_ci            && out != NULL
576e1051a39Sopenharmony_ci            && OSSL_ENCODER_to_bio(ctx, out)
577e1051a39Sopenharmony_ci            && BIO_get_mem_ptr(out, &buf) > 0) {
578e1051a39Sopenharmony_ci            ret = buf->length;
579e1051a39Sopenharmony_ci
580e1051a39Sopenharmony_ci            if (pp != NULL) {
581e1051a39Sopenharmony_ci                if (*pp == NULL) {
582e1051a39Sopenharmony_ci                    *pp = (unsigned char *)buf->data;
583e1051a39Sopenharmony_ci                    buf->length = 0;
584e1051a39Sopenharmony_ci                    buf->data = NULL;
585e1051a39Sopenharmony_ci                } else {
586e1051a39Sopenharmony_ci                    memcpy(*pp, buf->data, ret);
587e1051a39Sopenharmony_ci                    *pp += ret;
588e1051a39Sopenharmony_ci                }
589e1051a39Sopenharmony_ci            }
590e1051a39Sopenharmony_ci        }
591e1051a39Sopenharmony_ci        BIO_free(out);
592e1051a39Sopenharmony_ci        OSSL_ENCODER_CTX_free(ctx);
593e1051a39Sopenharmony_ci    }
594e1051a39Sopenharmony_ci
595e1051a39Sopenharmony_ci    return ret;
596e1051a39Sopenharmony_ci}
597e1051a39Sopenharmony_ci
598e1051a39Sopenharmony_ci/*
599e1051a39Sopenharmony_ci * The following are equivalents but which return RSA and DSA keys
600e1051a39Sopenharmony_ci */
601e1051a39Sopenharmony_ciRSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
602e1051a39Sopenharmony_ci{
603e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
604e1051a39Sopenharmony_ci    RSA *key = NULL;
605e1051a39Sopenharmony_ci    const unsigned char *q;
606e1051a39Sopenharmony_ci
607e1051a39Sopenharmony_ci    q = *pp;
608e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
609e1051a39Sopenharmony_ci    if (pkey == NULL)
610e1051a39Sopenharmony_ci        return NULL;
611e1051a39Sopenharmony_ci    key = EVP_PKEY_get1_RSA(pkey);
612e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
613e1051a39Sopenharmony_ci    if (key == NULL)
614e1051a39Sopenharmony_ci        return NULL;
615e1051a39Sopenharmony_ci    *pp = q;
616e1051a39Sopenharmony_ci    if (a != NULL) {
617e1051a39Sopenharmony_ci        RSA_free(*a);
618e1051a39Sopenharmony_ci        *a = key;
619e1051a39Sopenharmony_ci    }
620e1051a39Sopenharmony_ci    return key;
621e1051a39Sopenharmony_ci}
622e1051a39Sopenharmony_ci
623e1051a39Sopenharmony_ciint i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp)
624e1051a39Sopenharmony_ci{
625e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
626e1051a39Sopenharmony_ci    int ret;
627e1051a39Sopenharmony_ci    if (!a)
628e1051a39Sopenharmony_ci        return 0;
629e1051a39Sopenharmony_ci    pktmp = EVP_PKEY_new();
630e1051a39Sopenharmony_ci    if (pktmp == NULL) {
631e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
632e1051a39Sopenharmony_ci        return -1;
633e1051a39Sopenharmony_ci    }
634e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign_RSA(pktmp, (RSA *)a);
635e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
636e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
637e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
638e1051a39Sopenharmony_ci    return ret;
639e1051a39Sopenharmony_ci}
640e1051a39Sopenharmony_ci
641e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
642e1051a39Sopenharmony_ciDH *ossl_d2i_DH_PUBKEY(DH **a, const unsigned char **pp, long length)
643e1051a39Sopenharmony_ci{
644e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
645e1051a39Sopenharmony_ci    DH *key = NULL;
646e1051a39Sopenharmony_ci    const unsigned char *q;
647e1051a39Sopenharmony_ci
648e1051a39Sopenharmony_ci    q = *pp;
649e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
650e1051a39Sopenharmony_ci    if (pkey == NULL)
651e1051a39Sopenharmony_ci        return NULL;
652e1051a39Sopenharmony_ci    if (EVP_PKEY_get_id(pkey) == EVP_PKEY_DH)
653e1051a39Sopenharmony_ci        key = EVP_PKEY_get1_DH(pkey);
654e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
655e1051a39Sopenharmony_ci    if (key == NULL)
656e1051a39Sopenharmony_ci        return NULL;
657e1051a39Sopenharmony_ci    *pp = q;
658e1051a39Sopenharmony_ci    if (a != NULL) {
659e1051a39Sopenharmony_ci        DH_free(*a);
660e1051a39Sopenharmony_ci        *a = key;
661e1051a39Sopenharmony_ci    }
662e1051a39Sopenharmony_ci    return key;
663e1051a39Sopenharmony_ci}
664e1051a39Sopenharmony_ci
665e1051a39Sopenharmony_ciint ossl_i2d_DH_PUBKEY(const DH *a, unsigned char **pp)
666e1051a39Sopenharmony_ci{
667e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
668e1051a39Sopenharmony_ci    int ret;
669e1051a39Sopenharmony_ci    if (!a)
670e1051a39Sopenharmony_ci        return 0;
671e1051a39Sopenharmony_ci    pktmp = EVP_PKEY_new();
672e1051a39Sopenharmony_ci    if (pktmp == NULL) {
673e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
674e1051a39Sopenharmony_ci        return -1;
675e1051a39Sopenharmony_ci    }
676e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign_DH(pktmp, (DH *)a);
677e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
678e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
679e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
680e1051a39Sopenharmony_ci    return ret;
681e1051a39Sopenharmony_ci}
682e1051a39Sopenharmony_ci
683e1051a39Sopenharmony_ciDH *ossl_d2i_DHx_PUBKEY(DH **a, const unsigned char **pp, long length)
684e1051a39Sopenharmony_ci{
685e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
686e1051a39Sopenharmony_ci    DH *key = NULL;
687e1051a39Sopenharmony_ci    const unsigned char *q;
688e1051a39Sopenharmony_ci
689e1051a39Sopenharmony_ci    q = *pp;
690e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
691e1051a39Sopenharmony_ci    if (pkey == NULL)
692e1051a39Sopenharmony_ci        return NULL;
693e1051a39Sopenharmony_ci    if (EVP_PKEY_get_id(pkey) == EVP_PKEY_DHX)
694e1051a39Sopenharmony_ci        key = EVP_PKEY_get1_DH(pkey);
695e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
696e1051a39Sopenharmony_ci    if (key == NULL)
697e1051a39Sopenharmony_ci        return NULL;
698e1051a39Sopenharmony_ci    *pp = q;
699e1051a39Sopenharmony_ci    if (a != NULL) {
700e1051a39Sopenharmony_ci        DH_free(*a);
701e1051a39Sopenharmony_ci        *a = key;
702e1051a39Sopenharmony_ci    }
703e1051a39Sopenharmony_ci    return key;
704e1051a39Sopenharmony_ci}
705e1051a39Sopenharmony_ci
706e1051a39Sopenharmony_ciint ossl_i2d_DHx_PUBKEY(const DH *a, unsigned char **pp)
707e1051a39Sopenharmony_ci{
708e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
709e1051a39Sopenharmony_ci    int ret;
710e1051a39Sopenharmony_ci    if (!a)
711e1051a39Sopenharmony_ci        return 0;
712e1051a39Sopenharmony_ci    pktmp = EVP_PKEY_new();
713e1051a39Sopenharmony_ci    if (pktmp == NULL) {
714e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
715e1051a39Sopenharmony_ci        return -1;
716e1051a39Sopenharmony_ci    }
717e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign(pktmp, EVP_PKEY_DHX, (DH *)a);
718e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
719e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
720e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
721e1051a39Sopenharmony_ci    return ret;
722e1051a39Sopenharmony_ci}
723e1051a39Sopenharmony_ci#endif
724e1051a39Sopenharmony_ci
725e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA
726e1051a39Sopenharmony_ciDSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
727e1051a39Sopenharmony_ci{
728e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
729e1051a39Sopenharmony_ci    DSA *key = NULL;
730e1051a39Sopenharmony_ci    const unsigned char *q;
731e1051a39Sopenharmony_ci
732e1051a39Sopenharmony_ci    q = *pp;
733e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
734e1051a39Sopenharmony_ci    if (pkey == NULL)
735e1051a39Sopenharmony_ci        return NULL;
736e1051a39Sopenharmony_ci    key = EVP_PKEY_get1_DSA(pkey);
737e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
738e1051a39Sopenharmony_ci    if (key == NULL)
739e1051a39Sopenharmony_ci        return NULL;
740e1051a39Sopenharmony_ci    *pp = q;
741e1051a39Sopenharmony_ci    if (a != NULL) {
742e1051a39Sopenharmony_ci        DSA_free(*a);
743e1051a39Sopenharmony_ci        *a = key;
744e1051a39Sopenharmony_ci    }
745e1051a39Sopenharmony_ci    return key;
746e1051a39Sopenharmony_ci}
747e1051a39Sopenharmony_ci
748e1051a39Sopenharmony_ci/* Called from decoders; disallows provided DSA keys without parameters. */
749e1051a39Sopenharmony_ciDSA *ossl_d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
750e1051a39Sopenharmony_ci{
751e1051a39Sopenharmony_ci    DSA *key = NULL;
752e1051a39Sopenharmony_ci    const unsigned char *data;
753e1051a39Sopenharmony_ci    const BIGNUM *p, *q, *g;
754e1051a39Sopenharmony_ci
755e1051a39Sopenharmony_ci    data = *pp;
756e1051a39Sopenharmony_ci    key = d2i_DSA_PUBKEY(NULL, &data, length);
757e1051a39Sopenharmony_ci    if (key == NULL)
758e1051a39Sopenharmony_ci        return NULL;
759e1051a39Sopenharmony_ci    DSA_get0_pqg(key, &p, &q, &g);
760e1051a39Sopenharmony_ci    if (p == NULL || q == NULL || g == NULL) {
761e1051a39Sopenharmony_ci        DSA_free(key);
762e1051a39Sopenharmony_ci        return NULL;
763e1051a39Sopenharmony_ci    }
764e1051a39Sopenharmony_ci    *pp = data;
765e1051a39Sopenharmony_ci    if (a != NULL) {
766e1051a39Sopenharmony_ci        DSA_free(*a);
767e1051a39Sopenharmony_ci        *a = key;
768e1051a39Sopenharmony_ci    }
769e1051a39Sopenharmony_ci    return key;
770e1051a39Sopenharmony_ci}
771e1051a39Sopenharmony_ci
772e1051a39Sopenharmony_ciint i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
773e1051a39Sopenharmony_ci{
774e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
775e1051a39Sopenharmony_ci    int ret;
776e1051a39Sopenharmony_ci    if (!a)
777e1051a39Sopenharmony_ci        return 0;
778e1051a39Sopenharmony_ci    pktmp = EVP_PKEY_new();
779e1051a39Sopenharmony_ci    if (pktmp == NULL) {
780e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
781e1051a39Sopenharmony_ci        return -1;
782e1051a39Sopenharmony_ci    }
783e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign_DSA(pktmp, (DSA *)a);
784e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
785e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
786e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
787e1051a39Sopenharmony_ci    return ret;
788e1051a39Sopenharmony_ci}
789e1051a39Sopenharmony_ci#endif
790e1051a39Sopenharmony_ci
791e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC
792e1051a39Sopenharmony_ciEC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
793e1051a39Sopenharmony_ci{
794e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
795e1051a39Sopenharmony_ci    EC_KEY *key = NULL;
796e1051a39Sopenharmony_ci    const unsigned char *q;
797e1051a39Sopenharmony_ci    int type;
798e1051a39Sopenharmony_ci
799e1051a39Sopenharmony_ci    q = *pp;
800e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
801e1051a39Sopenharmony_ci    if (pkey == NULL)
802e1051a39Sopenharmony_ci        return NULL;
803e1051a39Sopenharmony_ci    type = EVP_PKEY_get_id(pkey);
804e1051a39Sopenharmony_ci    if (type == EVP_PKEY_EC || type == EVP_PKEY_SM2)
805e1051a39Sopenharmony_ci        key = EVP_PKEY_get1_EC_KEY(pkey);
806e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
807e1051a39Sopenharmony_ci    if (key == NULL)
808e1051a39Sopenharmony_ci        return NULL;
809e1051a39Sopenharmony_ci    *pp = q;
810e1051a39Sopenharmony_ci    if (a != NULL) {
811e1051a39Sopenharmony_ci        EC_KEY_free(*a);
812e1051a39Sopenharmony_ci        *a = key;
813e1051a39Sopenharmony_ci    }
814e1051a39Sopenharmony_ci    return key;
815e1051a39Sopenharmony_ci}
816e1051a39Sopenharmony_ci
817e1051a39Sopenharmony_ciint i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
818e1051a39Sopenharmony_ci{
819e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
820e1051a39Sopenharmony_ci    int ret;
821e1051a39Sopenharmony_ci
822e1051a39Sopenharmony_ci    if (a == NULL)
823e1051a39Sopenharmony_ci        return 0;
824e1051a39Sopenharmony_ci    if ((pktmp = EVP_PKEY_new()) == NULL) {
825e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
826e1051a39Sopenharmony_ci        return -1;
827e1051a39Sopenharmony_ci    }
828e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign_EC_KEY(pktmp, (EC_KEY *)a);
829e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
830e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
831e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
832e1051a39Sopenharmony_ci    return ret;
833e1051a39Sopenharmony_ci}
834e1051a39Sopenharmony_ci
835e1051a39Sopenharmony_ciECX_KEY *ossl_d2i_ED25519_PUBKEY(ECX_KEY **a,
836e1051a39Sopenharmony_ci                                 const unsigned char **pp, long length)
837e1051a39Sopenharmony_ci{
838e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
839e1051a39Sopenharmony_ci    ECX_KEY *key = NULL;
840e1051a39Sopenharmony_ci    const unsigned char *q;
841e1051a39Sopenharmony_ci
842e1051a39Sopenharmony_ci    q = *pp;
843e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
844e1051a39Sopenharmony_ci    if (pkey == NULL)
845e1051a39Sopenharmony_ci        return NULL;
846e1051a39Sopenharmony_ci    key = ossl_evp_pkey_get1_ED25519(pkey);
847e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
848e1051a39Sopenharmony_ci    if (key == NULL)
849e1051a39Sopenharmony_ci        return NULL;
850e1051a39Sopenharmony_ci    *pp = q;
851e1051a39Sopenharmony_ci    if (a != NULL) {
852e1051a39Sopenharmony_ci        ossl_ecx_key_free(*a);
853e1051a39Sopenharmony_ci        *a = key;
854e1051a39Sopenharmony_ci    }
855e1051a39Sopenharmony_ci    return key;
856e1051a39Sopenharmony_ci}
857e1051a39Sopenharmony_ci
858e1051a39Sopenharmony_ciint ossl_i2d_ED25519_PUBKEY(const ECX_KEY *a, unsigned char **pp)
859e1051a39Sopenharmony_ci{
860e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
861e1051a39Sopenharmony_ci    int ret;
862e1051a39Sopenharmony_ci
863e1051a39Sopenharmony_ci    if (a == NULL)
864e1051a39Sopenharmony_ci        return 0;
865e1051a39Sopenharmony_ci    if ((pktmp = EVP_PKEY_new()) == NULL) {
866e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
867e1051a39Sopenharmony_ci        return -1;
868e1051a39Sopenharmony_ci    }
869e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED25519, (ECX_KEY *)a);
870e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
871e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
872e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
873e1051a39Sopenharmony_ci    return ret;
874e1051a39Sopenharmony_ci}
875e1051a39Sopenharmony_ci
876e1051a39Sopenharmony_ciECX_KEY *ossl_d2i_ED448_PUBKEY(ECX_KEY **a,
877e1051a39Sopenharmony_ci                               const unsigned char **pp, long length)
878e1051a39Sopenharmony_ci{
879e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
880e1051a39Sopenharmony_ci    ECX_KEY *key = NULL;
881e1051a39Sopenharmony_ci    const unsigned char *q;
882e1051a39Sopenharmony_ci
883e1051a39Sopenharmony_ci    q = *pp;
884e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
885e1051a39Sopenharmony_ci    if (pkey == NULL)
886e1051a39Sopenharmony_ci        return NULL;
887e1051a39Sopenharmony_ci    if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448)
888e1051a39Sopenharmony_ci        key = ossl_evp_pkey_get1_ED448(pkey);
889e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
890e1051a39Sopenharmony_ci    if (key == NULL)
891e1051a39Sopenharmony_ci        return NULL;
892e1051a39Sopenharmony_ci    *pp = q;
893e1051a39Sopenharmony_ci    if (a != NULL) {
894e1051a39Sopenharmony_ci        ossl_ecx_key_free(*a);
895e1051a39Sopenharmony_ci        *a = key;
896e1051a39Sopenharmony_ci    }
897e1051a39Sopenharmony_ci    return key;
898e1051a39Sopenharmony_ci}
899e1051a39Sopenharmony_ci
900e1051a39Sopenharmony_ciint ossl_i2d_ED448_PUBKEY(const ECX_KEY *a, unsigned char **pp)
901e1051a39Sopenharmony_ci{
902e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
903e1051a39Sopenharmony_ci    int ret;
904e1051a39Sopenharmony_ci
905e1051a39Sopenharmony_ci    if (a == NULL)
906e1051a39Sopenharmony_ci        return 0;
907e1051a39Sopenharmony_ci    if ((pktmp = EVP_PKEY_new()) == NULL) {
908e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
909e1051a39Sopenharmony_ci        return -1;
910e1051a39Sopenharmony_ci    }
911e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED448, (ECX_KEY *)a);
912e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
913e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
914e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
915e1051a39Sopenharmony_ci    return ret;
916e1051a39Sopenharmony_ci}
917e1051a39Sopenharmony_ci
918e1051a39Sopenharmony_ciECX_KEY *ossl_d2i_X25519_PUBKEY(ECX_KEY **a,
919e1051a39Sopenharmony_ci                                const unsigned char **pp, long length)
920e1051a39Sopenharmony_ci{
921e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
922e1051a39Sopenharmony_ci    ECX_KEY *key = NULL;
923e1051a39Sopenharmony_ci    const unsigned char *q;
924e1051a39Sopenharmony_ci
925e1051a39Sopenharmony_ci    q = *pp;
926e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
927e1051a39Sopenharmony_ci    if (pkey == NULL)
928e1051a39Sopenharmony_ci        return NULL;
929e1051a39Sopenharmony_ci    if (EVP_PKEY_get_id(pkey) == EVP_PKEY_X25519)
930e1051a39Sopenharmony_ci        key = ossl_evp_pkey_get1_X25519(pkey);
931e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
932e1051a39Sopenharmony_ci    if (key == NULL)
933e1051a39Sopenharmony_ci        return NULL;
934e1051a39Sopenharmony_ci    *pp = q;
935e1051a39Sopenharmony_ci    if (a != NULL) {
936e1051a39Sopenharmony_ci        ossl_ecx_key_free(*a);
937e1051a39Sopenharmony_ci        *a = key;
938e1051a39Sopenharmony_ci    }
939e1051a39Sopenharmony_ci    return key;
940e1051a39Sopenharmony_ci}
941e1051a39Sopenharmony_ci
942e1051a39Sopenharmony_ciint ossl_i2d_X25519_PUBKEY(const ECX_KEY *a, unsigned char **pp)
943e1051a39Sopenharmony_ci{
944e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
945e1051a39Sopenharmony_ci    int ret;
946e1051a39Sopenharmony_ci
947e1051a39Sopenharmony_ci    if (a == NULL)
948e1051a39Sopenharmony_ci        return 0;
949e1051a39Sopenharmony_ci    if ((pktmp = EVP_PKEY_new()) == NULL) {
950e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
951e1051a39Sopenharmony_ci        return -1;
952e1051a39Sopenharmony_ci    }
953e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X25519, (ECX_KEY *)a);
954e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
955e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
956e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
957e1051a39Sopenharmony_ci    return ret;
958e1051a39Sopenharmony_ci}
959e1051a39Sopenharmony_ci
960e1051a39Sopenharmony_ciECX_KEY *ossl_d2i_X448_PUBKEY(ECX_KEY **a,
961e1051a39Sopenharmony_ci                              const unsigned char **pp, long length)
962e1051a39Sopenharmony_ci{
963e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
964e1051a39Sopenharmony_ci    ECX_KEY *key = NULL;
965e1051a39Sopenharmony_ci    const unsigned char *q;
966e1051a39Sopenharmony_ci
967e1051a39Sopenharmony_ci    q = *pp;
968e1051a39Sopenharmony_ci    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
969e1051a39Sopenharmony_ci    if (pkey == NULL)
970e1051a39Sopenharmony_ci        return NULL;
971e1051a39Sopenharmony_ci    if (EVP_PKEY_get_id(pkey) == EVP_PKEY_X448)
972e1051a39Sopenharmony_ci        key = ossl_evp_pkey_get1_X448(pkey);
973e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
974e1051a39Sopenharmony_ci    if (key == NULL)
975e1051a39Sopenharmony_ci        return NULL;
976e1051a39Sopenharmony_ci    *pp = q;
977e1051a39Sopenharmony_ci    if (a != NULL) {
978e1051a39Sopenharmony_ci        ossl_ecx_key_free(*a);
979e1051a39Sopenharmony_ci        *a = key;
980e1051a39Sopenharmony_ci    }
981e1051a39Sopenharmony_ci    return key;
982e1051a39Sopenharmony_ci}
983e1051a39Sopenharmony_ci
984e1051a39Sopenharmony_ciint ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp)
985e1051a39Sopenharmony_ci{
986e1051a39Sopenharmony_ci    EVP_PKEY *pktmp;
987e1051a39Sopenharmony_ci    int ret;
988e1051a39Sopenharmony_ci
989e1051a39Sopenharmony_ci    if (a == NULL)
990e1051a39Sopenharmony_ci        return 0;
991e1051a39Sopenharmony_ci    if ((pktmp = EVP_PKEY_new()) == NULL) {
992e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
993e1051a39Sopenharmony_ci        return -1;
994e1051a39Sopenharmony_ci    }
995e1051a39Sopenharmony_ci    (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X448, (ECX_KEY *)a);
996e1051a39Sopenharmony_ci    ret = i2d_PUBKEY(pktmp, pp);
997e1051a39Sopenharmony_ci    pktmp->pkey.ptr = NULL;
998e1051a39Sopenharmony_ci    EVP_PKEY_free(pktmp);
999e1051a39Sopenharmony_ci    return ret;
1000e1051a39Sopenharmony_ci}
1001e1051a39Sopenharmony_ci
1002e1051a39Sopenharmony_ci#endif
1003e1051a39Sopenharmony_ci
1004e1051a39Sopenharmony_ciint X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
1005e1051a39Sopenharmony_ci                           int ptype, void *pval,
1006e1051a39Sopenharmony_ci                           unsigned char *penc, int penclen)
1007e1051a39Sopenharmony_ci{
1008e1051a39Sopenharmony_ci    if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
1009e1051a39Sopenharmony_ci        return 0;
1010e1051a39Sopenharmony_ci    if (penc) {
1011e1051a39Sopenharmony_ci        OPENSSL_free(pub->public_key->data);
1012e1051a39Sopenharmony_ci        pub->public_key->data = penc;
1013e1051a39Sopenharmony_ci        pub->public_key->length = penclen;
1014e1051a39Sopenharmony_ci        /* Set number of unused bits to zero */
1015e1051a39Sopenharmony_ci        pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
1016e1051a39Sopenharmony_ci        pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
1017e1051a39Sopenharmony_ci    }
1018e1051a39Sopenharmony_ci    return 1;
1019e1051a39Sopenharmony_ci}
1020e1051a39Sopenharmony_ci
1021e1051a39Sopenharmony_ciint X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
1022e1051a39Sopenharmony_ci                           const unsigned char **pk, int *ppklen,
1023e1051a39Sopenharmony_ci                           X509_ALGOR **pa, const X509_PUBKEY *pub)
1024e1051a39Sopenharmony_ci{
1025e1051a39Sopenharmony_ci    if (ppkalg)
1026e1051a39Sopenharmony_ci        *ppkalg = pub->algor->algorithm;
1027e1051a39Sopenharmony_ci    if (pk) {
1028e1051a39Sopenharmony_ci        *pk = pub->public_key->data;
1029e1051a39Sopenharmony_ci        *ppklen = pub->public_key->length;
1030e1051a39Sopenharmony_ci    }
1031e1051a39Sopenharmony_ci    if (pa)
1032e1051a39Sopenharmony_ci        *pa = pub->algor;
1033e1051a39Sopenharmony_ci    return 1;
1034e1051a39Sopenharmony_ci}
1035e1051a39Sopenharmony_ci
1036e1051a39Sopenharmony_ciASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
1037e1051a39Sopenharmony_ci{
1038e1051a39Sopenharmony_ci    if (x == NULL)
1039e1051a39Sopenharmony_ci        return NULL;
1040e1051a39Sopenharmony_ci    return x->cert_info.key->public_key;
1041e1051a39Sopenharmony_ci}
1042e1051a39Sopenharmony_ci
1043e1051a39Sopenharmony_ci/* Returns 1 for equal, 0, for non-equal, < 0 on error */
1044e1051a39Sopenharmony_ciint X509_PUBKEY_eq(const X509_PUBKEY *a, const X509_PUBKEY *b)
1045e1051a39Sopenharmony_ci{
1046e1051a39Sopenharmony_ci    X509_ALGOR *algA, *algB;
1047e1051a39Sopenharmony_ci    EVP_PKEY *pA, *pB;
1048e1051a39Sopenharmony_ci
1049e1051a39Sopenharmony_ci    if (a == b)
1050e1051a39Sopenharmony_ci        return 1;
1051e1051a39Sopenharmony_ci    if (a == NULL || b == NULL)
1052e1051a39Sopenharmony_ci        return 0;
1053e1051a39Sopenharmony_ci    if (!X509_PUBKEY_get0_param(NULL, NULL, NULL, &algA, a) || algA == NULL
1054e1051a39Sopenharmony_ci        || !X509_PUBKEY_get0_param(NULL, NULL, NULL, &algB, b) || algB == NULL)
1055e1051a39Sopenharmony_ci        return -2;
1056e1051a39Sopenharmony_ci    if (X509_ALGOR_cmp(algA, algB) != 0)
1057e1051a39Sopenharmony_ci        return 0;
1058e1051a39Sopenharmony_ci    if ((pA = X509_PUBKEY_get0(a)) == NULL
1059e1051a39Sopenharmony_ci        || (pB = X509_PUBKEY_get0(b)) == NULL)
1060e1051a39Sopenharmony_ci        return -2;
1061e1051a39Sopenharmony_ci    return EVP_PKEY_eq(pA, pB);
1062e1051a39Sopenharmony_ci}
1063e1051a39Sopenharmony_ci
1064e1051a39Sopenharmony_ciint ossl_x509_PUBKEY_get0_libctx(OSSL_LIB_CTX **plibctx, const char **ppropq,
1065e1051a39Sopenharmony_ci                                 const X509_PUBKEY *key)
1066e1051a39Sopenharmony_ci{
1067e1051a39Sopenharmony_ci    if (plibctx)
1068e1051a39Sopenharmony_ci        *plibctx = key->libctx;
1069e1051a39Sopenharmony_ci    if (ppropq)
1070e1051a39Sopenharmony_ci        *ppropq = key->propq;
1071e1051a39Sopenharmony_ci    return 1;
1072e1051a39Sopenharmony_ci}
1073