1 /* $OpenBSD: x509_algor.c,v 1.6 2023/10/26 08:01:38 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 26 void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); 27 28 static int 29 x509_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 58 static int 59 x509_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 236 static int 237 x509_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 323 static int 324 x509_algor_set_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 X509_ALGOR_set_md(alg, EVP_sm3()); 335 X509_ALGOR_get0(&aobj, &ptype, NULL, alg); 336 if ((nid = OBJ_obj2nid(aobj)) != NID_sm3) { 337 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__, 338 NID_sm3, nid); 339 goto failure; 340 } 341 if (ptype != V_ASN1_UNDEF) { 342 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__, 343 V_ASN1_UNDEF, ptype); 344 goto failure; 345 } 346 347 /* Preallocate as recommended in the manual. */ 348 if (!X509_ALGOR_set0(alg, NULL, 0, NULL)) 349 errx(1, "%s: X509_ALGOR_set0", __func__); 350 351 X509_ALGOR_set_md(alg, EVP_md5()); 352 X509_ALGOR_get0(&aobj, &ptype, NULL, alg); 353 if ((nid = OBJ_obj2nid(aobj)) != NID_md5) { 354 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__, 355 NID_sm3, nid); 356 goto failure; 357 } 358 if (ptype != V_ASN1_NULL) { 359 fprintf(stderr, "%s: sm3 want %d, got %d\n", __func__, 360 V_ASN1_NULL, ptype); 361 goto failure; 362 } 363 364 failed = 0; 365 366 failure: 367 X509_ALGOR_free(alg); 368 369 return failed; 370 } 371 372 int 373 main(void) 374 { 375 int failed = 0; 376 377 failed |= x509_algor_new_test(); 378 failed |= x509_algor_set0_test(); 379 failed |= x509_algor_get0_test(); 380 failed |= x509_algor_set_md_test(); 381 382 return failed; 383 } 384