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