1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1998-2021 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#include <stddef.h>
11e1051a39Sopenharmony_ci#include <openssl/x509.h>
12e1051a39Sopenharmony_ci#include <openssl/asn1.h>
13e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
14e1051a39Sopenharmony_ci#include <openssl/err.h>
15e1051a39Sopenharmony_ci#include "crypto/asn1.h"
16e1051a39Sopenharmony_ci#include "crypto/evp.h"
17e1051a39Sopenharmony_ci
18e1051a39Sopenharmony_ciASN1_SEQUENCE(X509_ALGOR) = {
19e1051a39Sopenharmony_ci        ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
20e1051a39Sopenharmony_ci        ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
21e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(X509_ALGOR)
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE(X509_ALGORS) =
24e1051a39Sopenharmony_ci        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
25e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE_END(X509_ALGORS)
26e1051a39Sopenharmony_ci
27e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
28e1051a39Sopenharmony_ciIMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
29e1051a39Sopenharmony_ciIMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_ciint X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
32e1051a39Sopenharmony_ci{
33e1051a39Sopenharmony_ci    if (alg == NULL)
34e1051a39Sopenharmony_ci        return 0;
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    if (ptype != V_ASN1_UNDEF) {
37e1051a39Sopenharmony_ci        if (alg->parameter == NULL)
38e1051a39Sopenharmony_ci            alg->parameter = ASN1_TYPE_new();
39e1051a39Sopenharmony_ci        if (alg->parameter == NULL)
40e1051a39Sopenharmony_ci            return 0;
41e1051a39Sopenharmony_ci    }
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_ci    ASN1_OBJECT_free(alg->algorithm);
44e1051a39Sopenharmony_ci    alg->algorithm = aobj;
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci    if (ptype == 0)
47e1051a39Sopenharmony_ci        return 1;
48e1051a39Sopenharmony_ci    if (ptype == V_ASN1_UNDEF) {
49e1051a39Sopenharmony_ci        ASN1_TYPE_free(alg->parameter);
50e1051a39Sopenharmony_ci        alg->parameter = NULL;
51e1051a39Sopenharmony_ci    } else
52e1051a39Sopenharmony_ci        ASN1_TYPE_set(alg->parameter, ptype, pval);
53e1051a39Sopenharmony_ci    return 1;
54e1051a39Sopenharmony_ci}
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_civoid X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype,
57e1051a39Sopenharmony_ci                     const void **ppval, const X509_ALGOR *algor)
58e1051a39Sopenharmony_ci{
59e1051a39Sopenharmony_ci    if (paobj)
60e1051a39Sopenharmony_ci        *paobj = algor->algorithm;
61e1051a39Sopenharmony_ci    if (pptype) {
62e1051a39Sopenharmony_ci        if (algor->parameter == NULL) {
63e1051a39Sopenharmony_ci            *pptype = V_ASN1_UNDEF;
64e1051a39Sopenharmony_ci            return;
65e1051a39Sopenharmony_ci        } else
66e1051a39Sopenharmony_ci            *pptype = algor->parameter->type;
67e1051a39Sopenharmony_ci        if (ppval)
68e1051a39Sopenharmony_ci            *ppval = algor->parameter->value.ptr;
69e1051a39Sopenharmony_ci    }
70e1051a39Sopenharmony_ci}
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_civoid X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
75e1051a39Sopenharmony_ci{
76e1051a39Sopenharmony_ci    int param_type;
77e1051a39Sopenharmony_ci
78e1051a39Sopenharmony_ci    if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT)
79e1051a39Sopenharmony_ci        param_type = V_ASN1_UNDEF;
80e1051a39Sopenharmony_ci    else
81e1051a39Sopenharmony_ci        param_type = V_ASN1_NULL;
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_ci    X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_get_type(md)), param_type, NULL);
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci}
86e1051a39Sopenharmony_ci
87e1051a39Sopenharmony_ciint X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
88e1051a39Sopenharmony_ci{
89e1051a39Sopenharmony_ci    int rv;
90e1051a39Sopenharmony_ci    rv = OBJ_cmp(a->algorithm, b->algorithm);
91e1051a39Sopenharmony_ci    if (rv)
92e1051a39Sopenharmony_ci        return rv;
93e1051a39Sopenharmony_ci    if (!a->parameter && !b->parameter)
94e1051a39Sopenharmony_ci        return 0;
95e1051a39Sopenharmony_ci    return ASN1_TYPE_cmp(a->parameter, b->parameter);
96e1051a39Sopenharmony_ci}
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_ciint X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
99e1051a39Sopenharmony_ci{
100e1051a39Sopenharmony_ci    if (src == NULL || dest == NULL)
101e1051a39Sopenharmony_ci        return 0;
102e1051a39Sopenharmony_ci
103e1051a39Sopenharmony_ci    if (dest->algorithm)
104e1051a39Sopenharmony_ci         ASN1_OBJECT_free(dest->algorithm);
105e1051a39Sopenharmony_ci    dest->algorithm = NULL;
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_ci    if (dest->parameter)
108e1051a39Sopenharmony_ci        ASN1_TYPE_free(dest->parameter);
109e1051a39Sopenharmony_ci    dest->parameter = NULL;
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_ci    if (src->algorithm)
112e1051a39Sopenharmony_ci        if ((dest->algorithm = OBJ_dup(src->algorithm)) == NULL)
113e1051a39Sopenharmony_ci            return 0;
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci    if (src->parameter != NULL) {
116e1051a39Sopenharmony_ci        dest->parameter = ASN1_TYPE_new();
117e1051a39Sopenharmony_ci        if (dest->parameter == NULL)
118e1051a39Sopenharmony_ci            return 0;
119e1051a39Sopenharmony_ci
120e1051a39Sopenharmony_ci        /* Assuming this is also correct for a BOOL.
121e1051a39Sopenharmony_ci         * set does copy as a side effect.
122e1051a39Sopenharmony_ci         */
123e1051a39Sopenharmony_ci        if (ASN1_TYPE_set1(dest->parameter, src->parameter->type,
124e1051a39Sopenharmony_ci                           src->parameter->value.ptr) == 0)
125e1051a39Sopenharmony_ci            return 0;
126e1051a39Sopenharmony_ci    }
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_ci    return 1;
129e1051a39Sopenharmony_ci}
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ci/* allocate and set algorithm ID from EVP_MD, default SHA1 */
132e1051a39Sopenharmony_ciint ossl_x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md)
133e1051a39Sopenharmony_ci{
134e1051a39Sopenharmony_ci    /* Default is SHA1 so no need to create it - still success */
135e1051a39Sopenharmony_ci    if (md == NULL || EVP_MD_is_a(md, "SHA1"))
136e1051a39Sopenharmony_ci        return 1;
137e1051a39Sopenharmony_ci    *palg = X509_ALGOR_new();
138e1051a39Sopenharmony_ci    if (*palg == NULL)
139e1051a39Sopenharmony_ci        return 0;
140e1051a39Sopenharmony_ci    X509_ALGOR_set_md(*palg, md);
141e1051a39Sopenharmony_ci    return 1;
142e1051a39Sopenharmony_ci}
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci/* convert algorithm ID to EVP_MD, default SHA1 */
145e1051a39Sopenharmony_ciconst EVP_MD *ossl_x509_algor_get_md(X509_ALGOR *alg)
146e1051a39Sopenharmony_ci{
147e1051a39Sopenharmony_ci    const EVP_MD *md;
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci    if (alg == NULL)
150e1051a39Sopenharmony_ci        return EVP_sha1();
151e1051a39Sopenharmony_ci    md = EVP_get_digestbyobj(alg->algorithm);
152e1051a39Sopenharmony_ci    if (md == NULL)
153e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_DIGEST);
154e1051a39Sopenharmony_ci    return md;
155e1051a39Sopenharmony_ci}
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ciX509_ALGOR *ossl_x509_algor_mgf1_decode(X509_ALGOR *alg)
158e1051a39Sopenharmony_ci{
159e1051a39Sopenharmony_ci    if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
160e1051a39Sopenharmony_ci        return NULL;
161e1051a39Sopenharmony_ci    return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
162e1051a39Sopenharmony_ci                                     alg->parameter);
163e1051a39Sopenharmony_ci}
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ci/* Allocate and set MGF1 algorithm ID from EVP_MD */
166e1051a39Sopenharmony_ciint ossl_x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
167e1051a39Sopenharmony_ci{
168e1051a39Sopenharmony_ci    X509_ALGOR *algtmp = NULL;
169e1051a39Sopenharmony_ci    ASN1_STRING *stmp = NULL;
170e1051a39Sopenharmony_ci
171e1051a39Sopenharmony_ci    *palg = NULL;
172e1051a39Sopenharmony_ci    if (mgf1md == NULL || EVP_MD_is_a(mgf1md, "SHA1"))
173e1051a39Sopenharmony_ci        return 1;
174e1051a39Sopenharmony_ci    /* need to embed algorithm ID inside another */
175e1051a39Sopenharmony_ci    if (!ossl_x509_algor_new_from_md(&algtmp, mgf1md))
176e1051a39Sopenharmony_ci        goto err;
177e1051a39Sopenharmony_ci    if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
178e1051a39Sopenharmony_ci         goto err;
179e1051a39Sopenharmony_ci    *palg = X509_ALGOR_new();
180e1051a39Sopenharmony_ci    if (*palg == NULL)
181e1051a39Sopenharmony_ci        goto err;
182e1051a39Sopenharmony_ci    X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
183e1051a39Sopenharmony_ci    stmp = NULL;
184e1051a39Sopenharmony_ci err:
185e1051a39Sopenharmony_ci    ASN1_STRING_free(stmp);
186e1051a39Sopenharmony_ci    X509_ALGOR_free(algtmp);
187e1051a39Sopenharmony_ci    if (*palg != NULL)
188e1051a39Sopenharmony_ci        return 1;
189e1051a39Sopenharmony_ci    return 0;
190e1051a39Sopenharmony_ci}
191