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 18 ASN1_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 23 ASN1_ITEM_TEMPLATE(X509_ALGORS) = 24 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR) 25 ASN1_ITEM_TEMPLATE_END(X509_ALGORS) 26 27 IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR) 28 IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS) 29 IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR) 30 31 int 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 56 void 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 74 void 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 87 int 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 98 int 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 */ 132 int 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 */ 145 const 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 157 X509_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 */ 166 int 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 if (!X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp)) { 183 X509_ALGOR_free(*palg); 184 *palg = NULL; 185 goto err; 186 } 187 stmp = NULL; 188 err: 189 ASN1_STRING_free(stmp); 190 X509_ALGOR_free(algtmp); 191 if (*palg != NULL) 192 return 1; 193 return 0; 194 } 195