1/* $OpenBSD: x509_algor.c,v 1.7 2024/02/29 20:03:47 tb Exp $ */ 2/* 3 * Copyright (c) 2023 Theo Buehler <tb@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <err.h> 19#include <stdio.h> 20 21#include <openssl/asn1.h> 22#include <openssl/evp.h> 23#include <openssl/objects.h> 24#include <openssl/x509.h> 25 26int X509_ALGOR_set_evp_md(X509_ALGOR *alg, const EVP_MD *md); 27 28static int 29x509_algor_new_test(void) 30{ 31 X509_ALGOR *alg = NULL; 32 const ASN1_OBJECT *aobj; 33 int failed = 1; 34 35 if ((alg = X509_ALGOR_new()) == NULL) 36 errx(1, "%s: X509_ALGOR_new", __func__); 37 38 if ((aobj = OBJ_nid2obj(NID_undef)) == NULL) 39 errx(1, "%s: OBJ_nid2obj", __func__); 40 41 if (alg->algorithm != aobj) { 42 fprintf(stderr, "FAIL: %s: want NID_undef OID\n", __func__); 43 goto failure; 44 } 45 if (alg->parameter != NULL) { 46 fprintf(stderr, "FAIL: %s: want NULL parameters\n", __func__); 47 goto failure; 48 } 49 50 failed = 0; 51 52 failure: 53 X509_ALGOR_free(alg); 54 55 return failed; 56} 57 58static int 59x509_algor_set0_test(void) 60{ 61 X509_ALGOR *alg = NULL; 62 ASN1_TYPE *old_parameter; 63 ASN1_OBJECT *oid; 64 ASN1_INTEGER *aint = NULL, *aint_ref; 65 int ret; 66 int failed = 1; 67 68 if ((ret = X509_ALGOR_set0(NULL, NULL, 0, NULL)) != 0) { 69 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(NULL, NULL, 0, NULL)" 70 ", want: %d, got %d\n", __func__, 0, ret); 71 goto failure; 72 } 73 74 if ((alg = X509_ALGOR_new()) == NULL) 75 errx(1, "%s: X509_ALGOR_new", __func__); 76 77 /* This sets algorithm to NULL and allocates new parameters. */ 78 if ((ret = X509_ALGOR_set0(alg, NULL, 0, NULL)) != 1) { 79 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, NULL)" 80 ", want: %d, got %d\n", __func__, 1, ret); 81 goto failure; 82 } 83 if (alg->algorithm != NULL) { 84 fprintf(stderr, "FAIL: %s: want NULL algorithm after " 85 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__); 86 goto failure; 87 } 88 if ((old_parameter = alg->parameter) == NULL) { 89 fprintf(stderr, "FAIL: %s: want non-NULL parameter after " 90 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__); 91 goto failure; 92 } 93 if (alg->parameter->type != V_ASN1_UNDEF) { 94 fprintf(stderr, "FAIL: %s: want %d parameter type after " 95 "X509_ALGOR_set0(alg, NULL, 0, NULL), got %d\n", 96 __func__, V_ASN1_UNDEF, alg->parameter->type); 97 goto failure; 98 } 99 if (alg->parameter->value.ptr != NULL) { 100 fprintf(stderr, "FAIL: %s: want NULL parameter value after " 101 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__); 102 goto failure; 103 } 104 105 /* This should leave algorithm at NULL and parameters untouched. */ 106 if ((ret = X509_ALGOR_set0(alg, NULL, 0, NULL)) != 1) { 107 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, NULL)" 108 ", want: %d, got %d\n", __func__, 1, ret); 109 goto failure; 110 } 111 if (alg->algorithm != NULL) { 112 fprintf(stderr, "FAIL: %s: want NULL algorithm after second" 113 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__); 114 goto failure; 115 } 116 if (alg->parameter != old_parameter) { 117 fprintf(stderr, "FAIL: %s: parameter changed after second" 118 "X509_ALGOR_set0(alg, NULL, 0, NULL)\n", __func__); 119 goto failure; 120 } 121 122 /* This ignores pval (old_parameter). */ 123 if ((ret = X509_ALGOR_set0(alg, NULL, 0, old_parameter)) != 1) { 124 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, ptr)" 125 ", want: %d, got %d\n", __func__, 1, ret); 126 goto failure; 127 } 128 if (alg->algorithm != NULL) { 129 fprintf(stderr, "FAIL: %s: want NULL algorithm after " 130 "X509_ALGOR_set0(alg, NULL, 0, ptr)\n", __func__); 131 goto failure; 132 } 133 if (alg->parameter == NULL) { 134 fprintf(stderr, "FAIL: %s: want non-NULL parameter after " 135 "X509_ALGOR_set0(alg, NULL, 0, ptr)\n", __func__); 136 goto failure; 137 } 138 if (alg->parameter->type != V_ASN1_UNDEF) { 139 fprintf(stderr, "FAIL: %s: want %d parameter type after " 140 "X509_ALGOR_set0(alg, NULL, 0, ptr), got %d\n", 141 __func__, V_ASN1_UNDEF, alg->parameter->type); 142 goto failure; 143 } 144 if (alg->parameter->value.ptr != NULL) { 145 fprintf(stderr, "FAIL: %s: want NULL parameter value after " 146 "X509_ALGOR_set0(alg, NULL, 0, ptr)\n", __func__); 147 goto failure; 148 } 149 150 old_parameter = NULL; 151 152 /* This frees parameters and ignores pval. */ 153 if ((ret = X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)) != 1) { 154 fprintf(stderr, "FAIL: %s: " 155 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)" 156 ", want: %d, got %d\n", __func__, 1, ret); 157 goto failure; 158 } 159 if (alg->algorithm != NULL) { 160 fprintf(stderr, "FAIL: %s: want NULL algorithm after " 161 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)\n", __func__); 162 goto failure; 163 } 164 if (alg->parameter != NULL) { 165 fprintf(stderr, "FAIL: %s: want NULL parameter after " 166 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, NULL)\n", __func__); 167 goto failure; 168 } 169 170 /* This frees parameters and ignores "foo". */ 171 if ((ret = X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, "foo")) != 1) { 172 fprintf(stderr, "FAIL: %s: X509_ALGOR_set0(alg, NULL, 0, \"foo\")" 173 ", want: %d, got %d\n", __func__, 1, ret); 174 goto failure; 175 } 176 if (alg->algorithm != NULL) { 177 fprintf(stderr, "FAIL: %s: want NULL algorithm after " 178 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, \"foo\")\n", __func__); 179 goto failure; 180 } 181 if (alg->parameter != NULL) { 182 fprintf(stderr, "FAIL: %s: want NULL parameter after " 183 "X509_ALGOR_set0(alg, NULL, V_ASN1_UNDEF, \"foo\")\n", __func__); 184 goto failure; 185 } 186 187 if ((oid = OBJ_nid2obj(NID_sha512_224)) == NULL) { 188 fprintf(stderr, "FAIL: %s: OBJ_nid2obj(NID_sha512_224)\n", __func__); 189 goto failure; 190 } 191 if ((aint = aint_ref = ASN1_INTEGER_new()) == NULL) 192 errx(1, "%s: ASN1_INTEGER_new()", __func__); 193 if (!ASN1_INTEGER_set_uint64(aint, 57)) 194 errx(1, "%s: ASN1_INTEGER_set_uint64()", __func__); 195 196 if ((ret = X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)) != 1) { 197 fprintf(stderr, "Fail: %s: " 198 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)" 199 ", want: %d, got %d\n", __func__, 1, ret); 200 goto failure; 201 } 202 aint = NULL; 203 if (alg->algorithm != oid) { 204 fprintf(stderr, "FAIL: %s: unexpected oid on alg after " 205 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)" 206 ", want: %d, got %d\n", __func__, 1, ret); 207 goto failure; 208 } 209 if (alg->parameter == NULL) { 210 fprintf(stderr, "FAIL: %s: expected non-NULL parameter after " 211 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)" 212 ", want: %d, got %d\n", __func__, 1, ret); 213 goto failure; 214 } 215 if (alg->parameter->type != V_ASN1_INTEGER) { 216 fprintf(stderr, "FAIL: %s: want %d parameter type after " 217 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint), got %d\n", 218 __func__, V_ASN1_INTEGER, alg->parameter->type); 219 goto failure; 220 } 221 if (alg->parameter->value.asn1_string != aint_ref) { 222 fprintf(stderr, "FAIL: %s: unexpected parameter value after " 223 "X509_ALGOR_set0(alg, oid, V_ASN1_NULL, aint)\n", __func__); 224 goto failure; 225 } 226 227 failed = 0; 228 229 failure: 230 X509_ALGOR_free(alg); 231 ASN1_INTEGER_free(aint); 232 233 return failed; 234} 235 236static int 237x509_algor_get0_test(void) 238{ 239 X509_ALGOR *alg; 240 const ASN1_OBJECT *aobj = NULL; 241 int ptype = 0; 242 const void *pval = NULL; 243 ASN1_OBJECT *oid; 244 ASN1_INTEGER *aint = NULL, *aint_ref = NULL; 245 int ret; 246 int failed = 1; 247 248 if ((alg = X509_ALGOR_new()) == NULL) 249 errx(1, "%s: X509_ALGOR_new", __func__); 250 251 X509_ALGOR_get0(&aobj, NULL, NULL, alg); 252 if (aobj == NULL) { 253 fprintf(stderr, "FAIL: %s: expected non-NULL aobj\n", __func__); 254 goto failure; 255 } 256 X509_ALGOR_get0(NULL, &ptype, NULL, alg); 257 if (ptype != V_ASN1_UNDEF) { 258 fprintf(stderr, "FAIL: %s: want %d, got %d\n", 259 __func__, V_ASN1_UNDEF, ptype); 260 goto failure; 261 } 262 263 if ((oid = OBJ_nid2obj(NID_ED25519)) == NULL) 264 errx(1, "%s: OBJ_nid2obj(NID_ED25519)", __func__); 265 if ((aint = aint_ref = ASN1_INTEGER_new()) == NULL) 266 errx(1, "%s: ASN1_INTEGER_new()", __func__); 267 if (!ASN1_INTEGER_set_uint64(aint, 99)) 268 errx(1, "%s: ASN1_INTEGER_set_uint64()", __func__); 269 270 if ((ret = X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)) != 1) { 271 fprintf(stderr, "Fail: %s: " 272 "X509_ALGOR_set0(alg, oid, V_ASN1_INTEGER, aint)" 273 ", want: %d, got %d\n", __func__, 1, ret); 274 goto failure; 275 } 276 aint = NULL; 277 278 X509_ALGOR_get0(&aobj, NULL, NULL, alg); 279 if (aobj != oid) { 280 fprintf(stderr, "FAIL: %s: expected Ed25519 oid\n", __func__); 281 goto failure; 282 } 283 X509_ALGOR_get0(NULL, &ptype, NULL, alg); 284 if (ptype != V_ASN1_INTEGER) { 285 fprintf(stderr, "FAIL: %s: expected %d, got %d\n", 286 __func__, V_ASN1_INTEGER, ptype); 287 goto failure; 288 } 289 pval = oid; 290 X509_ALGOR_get0(NULL, NULL, &pval, alg); 291 if (pval != NULL) { 292 fprintf(stderr, "FAIL: %s: got non-NULL pval\n", __func__); 293 goto failure; 294 } 295 296 aobj = NULL; 297 ptype = V_ASN1_UNDEF; 298 pval = oid; 299 X509_ALGOR_get0(&aobj, &ptype, &pval, alg); 300 if (aobj != oid) { 301 fprintf(stderr, "FAIL: %s: expected Ed25519 oid 2\n", __func__); 302 goto failure; 303 } 304 if (ptype != V_ASN1_INTEGER) { 305 fprintf(stderr, "FAIL: %s: expected %d, got %d 2\n", 306 __func__, V_ASN1_INTEGER, ptype); 307 goto failure; 308 } 309 if (pval != aint_ref) { 310 fprintf(stderr, "FAIL: %s: expected ASN.1 integer\n", __func__); 311 goto failure; 312 } 313 314 failed = 0; 315 316 failure: 317 X509_ALGOR_free(alg); 318 ASN1_INTEGER_free(aint); 319 320 return failed; 321} 322 323static int 324x509_algor_set_evp_md_test(void) 325{ 326 X509_ALGOR *alg = NULL; 327 const ASN1_OBJECT *aobj; 328 int ptype = 0, nid = 0; 329 int failed = 1; 330 331 if ((alg = X509_ALGOR_new()) == NULL) 332 errx(1, "%s: X509_ALGOR_new", __func__); 333 334 if (!X509_ALGOR_set_evp_md(alg, EVP_sm3())) { 335 fprintf(stderr, "%s: X509_ALGOR_set_evp_md to sm3 failed\n", 336 __func__); 337 goto failure; 338 } 339 X509_ALGOR_get0(&aobj, &ptype, NULL, alg); 340 if ((nid = OBJ_obj2nid(aobj)) != NID_sm3) { 341 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__, 342 NID_sm3, nid); 343 goto failure; 344 } 345 if (ptype != V_ASN1_UNDEF) { 346 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__, 347 V_ASN1_UNDEF, ptype); 348 goto failure; 349 } 350 351 /* Preallocate as recommended in the manual. */ 352 if (!X509_ALGOR_set0(alg, NULL, 0, NULL)) 353 errx(1, "%s: X509_ALGOR_set0", __func__); 354 355 if (!X509_ALGOR_set_evp_md(alg, EVP_md5())) { 356 fprintf(stderr, "%s: X509_ALGOR_set_evp_md to md5 failed\n", 357 __func__); 358 goto failure; 359 } 360 X509_ALGOR_get0(&aobj, &ptype, NULL, alg); 361 if ((nid = OBJ_obj2nid(aobj)) != NID_md5) { 362 fprintf(stderr, "%s: md5 want %d, got %d\n", __func__, 363 NID_sm3, nid); 364 goto failure; 365 } 366 if (ptype != V_ASN1_NULL) { 367 fprintf(stderr, "%s: md5 want %d, got %d\n", __func__, 368 V_ASN1_NULL, ptype); 369 goto failure; 370 } 371 372 failed = 0; 373 374 failure: 375 X509_ALGOR_free(alg); 376 377 return failed; 378} 379 380int 381main(void) 382{ 383 int failed = 0; 384 385 failed |= x509_algor_new_test(); 386 failed |= x509_algor_set0_test(); 387 failed |= x509_algor_get0_test(); 388 failed |= x509_algor_set_evp_md_test(); 389 390 return failed; 391} 392