]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509/x509_cmp.c
threads_pthread.c: change inline to ossl_inline
[thirdparty/openssl.git] / crypto / x509 / x509_cmp.c
CommitLineData
b1322259 1/*
da1c088f 2 * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
d02b48c6 3 *
3e4b43b9 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
b1322259
RS
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
d02b48c6
RE
8 */
9
10#include <stdio.h>
b39fc560 11#include "internal/cryptlib.h"
ec577822
BM
12#include <openssl/asn1.h>
13#include <openssl/objects.h>
14#include <openssl/x509.h>
e947f396 15#include <openssl/x509v3.h>
47b4ccea 16#include <openssl/core_names.h>
25f2138b 17#include "crypto/x509.h"
d02b48c6 18
ccd86b68 19int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
0f113f3e
MC
20{
21 int i;
5cf6abd8 22 const X509_CINF *ai, *bi;
0f113f3e 23
e0331eb8
DDO
24 if (b == NULL)
25 return a != NULL;
26 if (a == NULL)
27 return -1;
5cf6abd8
DSH
28 ai = &a->cert_info;
29 bi = &b->cert_info;
81e49438 30 i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber);
bc64c5a6
DDO
31 if (i != 0)
32 return i < 0 ? -1 : 1;
26a7d938 33 return X509_NAME_cmp(ai->issuer, bi->issuer);
0f113f3e 34}
d02b48c6 35
cf1b7d96 36#ifndef OPENSSL_NO_MD5
6b691a5c 37unsigned long X509_issuer_and_serial_hash(X509 *a)
0f113f3e
MC
38{
39 unsigned long ret = 0;
bfb0641f 40 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
0f113f3e 41 unsigned char md[16];
b7e28c0b 42 char *f = NULL;
e72dbd8e 43 EVP_MD *digest = NULL;
0f113f3e 44
6e59a892
RL
45 if (ctx == NULL)
46 goto err;
5cf6abd8 47 f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0);
8130d654
MC
48 if (f == NULL)
49 goto err;
e72dbd8e
SL
50 digest = EVP_MD_fetch(a->libctx, SN_md5, a->propq);
51 if (digest == NULL)
52 goto err;
53
54 if (!EVP_DigestInit_ex(ctx, digest, NULL))
0f113f3e 55 goto err;
6e59a892 56 if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f)))
0f113f3e 57 goto err;
0f113f3e 58 if (!EVP_DigestUpdate
6e59a892 59 (ctx, (unsigned char *)a->cert_info.serialNumber.data,
81e49438 60 (unsigned long)a->cert_info.serialNumber.length))
0f113f3e 61 goto err;
6e59a892 62 if (!EVP_DigestFinal_ex(ctx, &(md[0]), NULL))
0f113f3e
MC
63 goto err;
64 ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
65 ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
66 ) & 0xffffffffL;
67 err:
b7e28c0b 68 OPENSSL_free(f);
e72dbd8e 69 EVP_MD_free(digest);
bfb0641f 70 EVP_MD_CTX_free(ctx);
26a7d938 71 return ret;
0f113f3e 72}
d02b48c6 73#endif
0f113f3e 74
ccd86b68 75int X509_issuer_name_cmp(const X509 *a, const X509 *b)
0f113f3e 76{
26a7d938 77 return X509_NAME_cmp(a->cert_info.issuer, b->cert_info.issuer);
0f113f3e 78}
d02b48c6 79
ccd86b68 80int X509_subject_name_cmp(const X509 *a, const X509 *b)
0f113f3e 81{
26a7d938 82 return X509_NAME_cmp(a->cert_info.subject, b->cert_info.subject);
0f113f3e 83}
d02b48c6 84
ccd86b68 85int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
0f113f3e 86{
26a7d938 87 return X509_NAME_cmp(a->crl.issuer, b->crl.issuer);
0f113f3e 88}
d02b48c6 89
edc54021 90int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
0f113f3e 91{
f2a04587
DDO
92 int rv;
93
94 if ((a->flags & EXFLAG_NO_FINGERPRINT) == 0
95 && (b->flags & EXFLAG_NO_FINGERPRINT) == 0)
96 rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
97 else
98 return -2;
bc64c5a6
DDO
99
100 return rv < 0 ? -1 : rv > 0;
0f113f3e 101}
edc54021 102
1421aead 103X509_NAME *X509_get_issuer_name(const X509 *a)
0f113f3e 104{
26a7d938 105 return a->cert_info.issuer;
0f113f3e 106}
d02b48c6 107
6b691a5c 108unsigned long X509_issuer_name_hash(X509 *x)
0f113f3e 109{
bf973d06 110 return X509_NAME_hash_ex(x->cert_info.issuer, NULL, NULL, NULL);
0f113f3e 111}
d02b48c6 112
0e0c6821
DSH
113#ifndef OPENSSL_NO_MD5
114unsigned long X509_issuer_name_hash_old(X509 *x)
0f113f3e 115{
26a7d938 116 return X509_NAME_hash_old(x->cert_info.issuer);
0f113f3e 117}
0e0c6821
DSH
118#endif
119
1421aead 120X509_NAME *X509_get_subject_name(const X509 *a)
0f113f3e 121{
26a7d938 122 return a->cert_info.subject;
0f113f3e 123}
d02b48c6 124
22293ea1 125ASN1_INTEGER *X509_get_serialNumber(X509 *a)
0f113f3e 126{
81e49438 127 return &a->cert_info.serialNumber;
0f113f3e 128}
d02b48c6 129
68c12bfc
DSH
130const ASN1_INTEGER *X509_get0_serialNumber(const X509 *a)
131{
132 return &a->cert_info.serialNumber;
133}
134
6b691a5c 135unsigned long X509_subject_name_hash(X509 *x)
0f113f3e 136{
bf973d06 137 return X509_NAME_hash_ex(x->cert_info.subject, NULL, NULL, NULL);
0f113f3e 138}
731d9c5f 139
0e0c6821
DSH
140#ifndef OPENSSL_NO_MD5
141unsigned long X509_subject_name_hash_old(X509 *x)
0f113f3e 142{
26a7d938 143 return X509_NAME_hash_old(x->cert_info.subject);
0f113f3e 144}
0e0c6821
DSH
145#endif
146
0f113f3e
MC
147/*
148 * Compare two certificates: they must be identical for this to work. NB:
149 * Although "cmp" operations are generally prototyped to take "const"
150 * arguments (eg. for use in STACKs), the way X509 handling is - these
151 * operations may involve ensuring the hashes are up-to-date and ensuring
152 * certain cert information is cached. So this is the point where the
153 * "depth-first" constification tree has to halt with an evil cast.
e947f396 154 */
ccd86b68 155int X509_cmp(const X509 *a, const X509 *b)
e947f396 156{
f2a04587 157 int rv = 0;
7e06a675 158
3bed88a3
DDO
159 if (a == b) /* for efficiency */
160 return 0;
0f113f3e 161
f2a04587
DDO
162 /* attempt to compute cert hash */
163 (void)X509_check_purpose((X509 *)a, -1, 0);
164 (void)X509_check_purpose((X509 *)b, -1, 0);
165
166 if ((a->ex_flags & EXFLAG_NO_FINGERPRINT) == 0
167 && (b->ex_flags & EXFLAG_NO_FINGERPRINT) == 0)
168 rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
bc64c5a6
DDO
169 if (rv != 0)
170 return rv < 0 ? -1 : 1;
f2a04587 171
0f113f3e 172 /* Check for match against stored encoding too */
5cf6abd8 173 if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) {
87a8405b
DB
174 if (a->cert_info.enc.len < b->cert_info.enc.len)
175 return -1;
176 if (a->cert_info.enc.len > b->cert_info.enc.len)
177 return 1;
bc64c5a6
DDO
178 rv = memcmp(a->cert_info.enc.enc,
179 b->cert_info.enc.enc, a->cert_info.enc.len);
0f113f3e 180 }
bc64c5a6 181 return rv < 0 ? -1 : rv > 0;
e947f396 182}
d02b48c6 183
c1be4d61 184int ossl_x509_add_cert_new(STACK_OF(X509) **p_sk, X509 *cert, int flags)
eeccc237 185{
0dca5ede 186 if (*p_sk == NULL && (*p_sk = sk_X509_new_null()) == NULL) {
e077455e 187 ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
eeccc237
DDO
188 return 0;
189 }
daf1300b 190 return X509_add_cert(*p_sk, cert, flags);
eeccc237
DDO
191}
192
193int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags)
194{
195 if (sk == NULL) {
9311d0c4 196 ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
eeccc237
DDO
197 return 0;
198 }
199 if ((flags & X509_ADD_FLAG_NO_DUP) != 0) {
200 /*
201 * not using sk_X509_set_cmp_func() and sk_X509_find()
202 * because this re-orders the certs on the stack
203 */
204 int i;
205
206 for (i = 0; i < sk_X509_num(sk); i++) {
207 if (X509_cmp(sk_X509_value(sk, i), cert) == 0)
208 return 1;
209 }
210 }
64c428c3
PH
211 if ((flags & X509_ADD_FLAG_NO_SS) != 0) {
212 int ret = X509_self_signed(cert, 0);
213
214 if (ret != 0)
215 return ret > 0 ? 1 : 0;
216 }
eeccc237
DDO
217 if (!sk_X509_insert(sk, cert,
218 (flags & X509_ADD_FLAG_PREPEND) != 0 ? 0 : -1)) {
e077455e 219 ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
eeccc237
DDO
220 return 0;
221 }
222 if ((flags & X509_ADD_FLAG_UP_REF) != 0)
223 (void)X509_up_ref(cert);
224 return 1;
225}
226
227int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags)
0dca5ede 228/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
eeccc237 229{
daf1300b
DDO
230 if (sk == NULL) {
231 ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
232 return 0;
233 }
234 return ossl_x509_add_certs_new(&sk, certs, flags);
235}
236
237int ossl_x509_add_certs_new(STACK_OF(X509) **p_sk, STACK_OF(X509) *certs,
238 int flags)
0dca5ede 239/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
daf1300b
DDO
240{
241 int n = sk_X509_num(certs /* may be NULL */);
eeccc237 242 int i;
bc64c5a6 243
eeccc237
DDO
244 for (i = 0; i < n; i++) {
245 int j = (flags & X509_ADD_FLAG_PREPEND) == 0 ? i : n - 1 - i;
246 /* if prepend, add certs in reverse order to keep original order */
247
c1be4d61 248 if (!ossl_x509_add_cert_new(p_sk, sk_X509_value(certs, j), flags))
eeccc237
DDO
249 return 0;
250 }
251 return 1;
252}
253
450ea834 254int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
0f113f3e
MC
255{
256 int ret;
c81a1509 257
e0331eb8
DDO
258 if (b == NULL)
259 return a != NULL;
260 if (a == NULL)
261 return -1;
c81a1509 262
e0331eb8 263 /* Ensure canonical encoding is present and up to date */
72ded6f2 264 if (a->canon_enc == NULL || a->modified) {
0f113f3e
MC
265 ret = i2d_X509_NAME((X509_NAME *)a, NULL);
266 if (ret < 0)
267 return -2;
268 }
1862dae8 269
72ded6f2 270 if (b->canon_enc == NULL || b->modified) {
0f113f3e
MC
271 ret = i2d_X509_NAME((X509_NAME *)b, NULL);
272 if (ret < 0)
273 return -2;
274 }
1862dae8 275
74bcbea7
TM
276 ret = a->canon_enclen - b->canon_enclen;
277 if (ret == 0 && a->canon_enclen == 0)
278 return 0;
279
ec597528
WD
280 if (ret == 0) {
281 if (a->canon_enc == NULL || b->canon_enc == NULL)
282 return -2;
bc64c5a6 283 ret = memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
ec597528 284 }
d02b48c6 285
bc64c5a6 286 return ret < 0 ? -1 : ret > 0;
0f113f3e 287}
d02b48c6 288
bf973d06
DDO
289unsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx,
290 const char *propq, int *ok)
0f113f3e
MC
291{
292 unsigned long ret = 0;
293 unsigned char md[SHA_DIGEST_LENGTH];
bf973d06 294 EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
945fde53 295 int i2d_ret;
0f113f3e
MC
296
297 /* Make sure X509_NAME structure contains valid cached encoding */
945fde53 298 i2d_ret = i2d_X509_NAME(x, NULL);
bf973d06
DDO
299 if (ok != NULL)
300 *ok = 0;
945fde53 301 if (i2d_ret >= 0 && sha1 != NULL
bf973d06
DDO
302 && EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, sha1, NULL)) {
303 ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
304 ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
305 ) & 0xffffffffL;
306 if (ok != NULL)
307 *ok = 1;
308 }
309 EVP_MD_free(sha1);
26a7d938 310 return ret;
0f113f3e 311}
450ea834 312
cf1b7d96 313#ifndef OPENSSL_NO_MD5
0f113f3e
MC
314/*
315 * I now DER encode the name and hash it. Since I cache the DER encoding,
316 * this is reasonably efficient.
317 */
8cc86b81 318unsigned long X509_NAME_hash_old(const X509_NAME *x)
0f113f3e 319{
47b4ccea 320 EVP_MD *md5 = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_MD5, "-fips");
bfb0641f 321 EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
0f113f3e
MC
322 unsigned long ret = 0;
323 unsigned char md[16];
324
47b4ccea
RL
325 if (md5 == NULL || md_ctx == NULL)
326 goto end;
6e59a892 327
0f113f3e 328 /* Make sure X509_NAME structure contains valid cached encoding */
945fde53 329 if (i2d_X509_NAME(x, NULL) < 0)
330 goto end;
331
47b4ccea 332 if (EVP_DigestInit_ex(md_ctx, md5, NULL)
6e59a892
RL
333 && EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length)
334 && EVP_DigestFinal_ex(md_ctx, md, NULL))
0f113f3e
MC
335 ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
336 ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
337 ) & 0xffffffffL;
47b4ccea
RL
338
339 end:
bfb0641f 340 EVP_MD_CTX_free(md_ctx);
47b4ccea 341 EVP_MD_free(md5);
0f113f3e 342
26a7d938 343 return ret;
0f113f3e 344}
d02b48c6
RE
345#endif
346
347/* Search a stack of X509 for a match */
8cc86b81
DDO
348X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, const X509_NAME *name,
349 const ASN1_INTEGER *serial)
0f113f3e
MC
350{
351 int i;
0f113f3e
MC
352 X509 x, *x509 = NULL;
353
354 if (!sk)
355 return NULL;
356
81e49438 357 x.cert_info.serialNumber = *serial;
8cc86b81 358 x.cert_info.issuer = (X509_NAME *)name; /* won't modify it */
0f113f3e
MC
359
360 for (i = 0; i < sk_X509_num(sk); i++) {
361 x509 = sk_X509_value(sk, i);
362 if (X509_issuer_and_serial_cmp(x509, &x) == 0)
26a7d938 363 return x509;
0f113f3e 364 }
26a7d938 365 return NULL;
0f113f3e 366}
d02b48c6 367
8cc86b81 368X509 *X509_find_by_subject(STACK_OF(X509) *sk, const X509_NAME *name)
0f113f3e
MC
369{
370 X509 *x509;
371 int i;
372
373 for (i = 0; i < sk_X509_num(sk); i++) {
374 x509 = sk_X509_value(sk, i);
375 if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0)
26a7d938 376 return x509;
0f113f3e 377 }
26a7d938 378 return NULL;
0f113f3e 379}
d02b48c6 380
fdaf7bee 381EVP_PKEY *X509_get0_pubkey(const X509 *x)
c01ff880
DSH
382{
383 if (x == NULL)
384 return NULL;
385 return X509_PUBKEY_get0(x->cert_info.key);
386}
387
6b691a5c 388EVP_PKEY *X509_get_pubkey(X509 *x)
0f113f3e 389{
5cf6abd8 390 if (x == NULL)
c01ff880
DSH
391 return NULL;
392 return X509_PUBKEY_get(x->cert_info.key);
0f113f3e 393}
dfeab068 394
aaabe580 395int X509_check_private_key(const X509 *cert, const EVP_PKEY *pkey)
0f113f3e 396{
aaabe580 397 const EVP_PKEY *xk = X509_get0_pubkey(cert);
0f113f3e 398
10af9769
P
399 if (xk == NULL) {
400 ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
401 return 0;
402 }
aaabe580
DDO
403 return ossl_x509_check_private_key(xk, pkey);
404}
0f113f3e 405
aaabe580
DDO
406int ossl_x509_check_private_key(const EVP_PKEY *x, const EVP_PKEY *pkey)
407{
408 if (x == NULL) {
409 ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
410 return 0;
411 }
412 switch (EVP_PKEY_eq(x, pkey)) {
413 case 1:
414 return 1;
0f113f3e 415 case 0:
9311d0c4 416 ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH);
aaabe580 417 return 0;
0f113f3e 418 case -1:
9311d0c4 419 ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH);
aaabe580 420 return 0;
0f113f3e 421 case -2:
9311d0c4 422 ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE);
aaabe580
DDO
423 /* fall thru */
424 default:
425 return 0;
0f113f3e 426 }
0f113f3e
MC
427}
428
429/*
430 * Check a suite B algorithm is permitted: pass in a public key and the NID
431 * of its signature (or 0 if no signature). The pflags is a pointer to a
432 * flags field which must contain the suite B verification flags.
3ad344a5
DSH
433 */
434
14536c8c
DSH
435#ifndef OPENSSL_NO_EC
436
3ad344a5 437static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
0f113f3e 438{
5b5eea4b
SL
439 char curve_name[80];
440 size_t curve_name_len;
0f113f3e 441 int curve_nid;
5b5eea4b
SL
442
443 if (pkey == NULL || !EVP_PKEY_is_a(pkey, "EC"))
0f113f3e 444 return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
5b5eea4b 445
0c8e98e6
TM
446 if (!EVP_PKEY_get_group_name(pkey, curve_name, sizeof(curve_name),
447 &curve_name_len))
5b5eea4b
SL
448 return X509_V_ERR_SUITE_B_INVALID_CURVE;
449
450 curve_nid = OBJ_txt2nid(curve_name);
0f113f3e
MC
451 /* Check curve is consistent with LOS */
452 if (curve_nid == NID_secp384r1) { /* P-384 */
453 /*
454 * Check signature algorithm is consistent with curve.
455 */
456 if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
457 return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
458 if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
459 return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
460 /* If we encounter P-384 we cannot use P-256 later */
461 *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
462 } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */
463 if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
464 return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
465 if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
466 return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
bc64c5a6 467 } else {
0f113f3e 468 return X509_V_ERR_SUITE_B_INVALID_CURVE;
bc64c5a6 469 }
0f113f3e
MC
470 return X509_V_OK;
471}
3ad344a5 472
3b0648eb 473int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
0f113f3e
MC
474 unsigned long flags)
475{
476 int rv, i, sign_nid;
6e328256
VD
477 EVP_PKEY *pk;
478 unsigned long tflags = flags;
479
0f113f3e
MC
480 if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
481 return X509_V_OK;
6e328256 482
0f113f3e
MC
483 /* If no EE certificate passed in must be first in chain */
484 if (x == NULL) {
485 x = sk_X509_value(chain, 0);
486 i = 1;
bc64c5a6 487 } else {
0f113f3e 488 i = 0;
bc64c5a6 489 }
6e328256
VD
490 pk = X509_get0_pubkey(x);
491
492 /*
493 * With DANE-EE(3) success, or DANE-EE(3)/PKIX-EE(1) failure we don't build
494 * a chain all, just report trust success or failure, but must also report
495 * Suite-B errors if applicable. This is indicated via a NULL chain
496 * pointer. All we need to do is check the leaf key algorithm.
497 */
498 if (chain == NULL)
499 return check_suite_b(pk, -1, &tflags);
500
cdf63a37 501 if (X509_get_version(x) != X509_VERSION_3) {
0f113f3e
MC
502 rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
503 /* Correct error depth */
504 i = 0;
505 goto end;
506 }
507
0f113f3e
MC
508 /* Check EE key only */
509 rv = check_suite_b(pk, -1, &tflags);
510 if (rv != X509_V_OK) {
511 /* Correct error depth */
512 i = 0;
513 goto end;
514 }
515 for (; i < sk_X509_num(chain); i++) {
516 sign_nid = X509_get_signature_nid(x);
517 x = sk_X509_value(chain, i);
cdf63a37 518 if (X509_get_version(x) != X509_VERSION_3) {
0f113f3e
MC
519 rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
520 goto end;
521 }
8382fd3a 522 pk = X509_get0_pubkey(x);
0f113f3e
MC
523 rv = check_suite_b(pk, sign_nid, &tflags);
524 if (rv != X509_V_OK)
525 goto end;
526 }
527
528 /* Final check: root CA signature */
529 rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
530 end:
0f113f3e
MC
531 if (rv != X509_V_OK) {
532 /* Invalid signature or LOS errors are for previous cert */
533 if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
534 || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
535 i--;
536 /*
537 * If we have LOS error and flags changed then we are signing P-384
0d4fb843 538 * with P-256. Use more meaningful error.
0f113f3e
MC
539 */
540 if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
541 rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
542 if (perror_depth)
543 *perror_depth = i;
544 }
545 return rv;
546}
3ad344a5 547
3b0648eb 548int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
0f113f3e
MC
549{
550 int sign_nid;
551 if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
552 return X509_V_OK;
6e63c142 553 sign_nid = OBJ_obj2nid(crl->crl.sig_alg.algorithm);
0f113f3e
MC
554 return check_suite_b(pk, sign_nid, &flags);
555}
14536c8c
DSH
556
557#else
558int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
0f113f3e
MC
559 unsigned long flags)
560{
561 return 0;
562}
14536c8c
DSH
563
564int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
0f113f3e
MC
565{
566 return 0;
567}
14536c8c
DSH
568
569#endif
d53b437f 570
0f113f3e
MC
571/*
572 * Not strictly speaking an "up_ref" as a STACK doesn't have a reference
573 * count but it has the same effect by duping the STACK and upping the ref of
574 * each X509 structure.
3b0648eb
DSH
575 */
576STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
0f113f3e 577{
d53b437f 578 STACK_OF(X509) *ret = sk_X509_dup(chain);
0f113f3e 579 int i;
d53b437f 580
cae665df
BE
581 if (ret == NULL)
582 return NULL;
0f113f3e
MC
583 for (i = 0; i < sk_X509_num(ret); i++) {
584 X509 *x = sk_X509_value(ret, i);
d53b437f 585
cae665df
BE
586 if (!X509_up_ref(x))
587 goto err;
0f113f3e
MC
588 }
589 return ret;
d53b437f 590
cae665df
BE
591 err:
592 while (i-- > 0)
bc64c5a6 593 X509_free(sk_X509_value(ret, i));
cae665df
BE
594 sk_X509_free(ret);
595 return NULL;
0f113f3e 596}