1 /* $OpenBSD: x509_siginfo.c,v 1.1 2024/08/28 07:15:04 tb Exp $ */ 2 3 /* 4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <openssl/evp.h> 20 #include <openssl/objects.h> 21 #include <openssl/x509.h> 22 23 #include "evp_local.h" 24 25 #include "x509_internal.h" 26 27 static int 28 x509_find_sigid_algs(const X509 *x509, int *out_md_nid, int *out_pkey_nid) 29 { 30 const ASN1_OBJECT *aobj; 31 int nid; 32 33 *out_md_nid = NID_undef; 34 *out_pkey_nid = NID_undef; 35 36 X509_ALGOR_get0(&aobj, NULL, NULL, x509->sig_alg); 37 if ((nid = OBJ_obj2nid(aobj)) == NID_undef) 38 return 0; 39 40 return OBJ_find_sigid_algs(nid, out_md_nid, out_pkey_nid); 41 } 42 43 int 44 X509_get_signature_info(X509 *x509, int *out_md_nid, int *out_pkey_nid, 45 int *out_security_bits, uint32_t *out_flags) 46 { 47 const EVP_MD *md; 48 int md_nid = NID_undef, pkey_nid = NID_undef, security_bits = -1; 49 uint32_t flags = 0; 50 51 if (out_md_nid != NULL) 52 *out_md_nid = md_nid; 53 if (out_pkey_nid != NULL) 54 *out_pkey_nid = pkey_nid; 55 if (out_security_bits != NULL) 56 *out_security_bits = security_bits; 57 if (out_flags != NULL) 58 *out_flags = flags; 59 60 if (!x509v3_cache_extensions(x509)) 61 goto err; 62 63 if (!x509_find_sigid_algs(x509, &md_nid, &pkey_nid)) 64 goto err; 65 66 /* 67 * If md_nid == NID_undef, this means we need to consult the ameth. 68 * Handlers are available for EdDSA and RSA-PSS. No other signature 69 * algorithm with NID_undef should appear in a certificate. 70 */ 71 if (md_nid == NID_undef) { 72 const EVP_PKEY_ASN1_METHOD *ameth; 73 74 if ((ameth = EVP_PKEY_asn1_find(NULL, pkey_nid)) == NULL || 75 ameth->signature_info == NULL) 76 goto err; 77 78 if (!ameth->signature_info(x509->sig_alg, &md_nid, &pkey_nid, 79 &security_bits, &flags)) 80 goto err; 81 82 goto done; 83 } 84 85 /* XXX - OpenSSL 3 special cases SHA-1 (63 bits) and MD5 (39 bits). */ 86 if ((md = EVP_get_digestbynid(md_nid)) == NULL) 87 goto err; 88 89 /* Assume 4 bits of collision resistance per octet. */ 90 if ((security_bits = EVP_MD_size(md)) <= 0) 91 goto err; 92 security_bits *= 4; 93 94 if (md_nid == NID_sha1 || md_nid == NID_sha256 || 95 md_nid == NID_sha384 || md_nid == NID_sha512) 96 flags |= X509_SIG_INFO_TLS; 97 98 flags |= X509_SIG_INFO_VALID; 99 100 done: 101 if (out_md_nid != NULL) 102 *out_md_nid = md_nid; 103 if (out_pkey_nid != NULL) 104 *out_pkey_nid = pkey_nid; 105 if (out_security_bits != NULL) 106 *out_security_bits = security_bits; 107 if (out_flags != NULL) 108 *out_flags = flags; 109 110 err: 111 return (flags & X509_SIG_INFO_VALID) != 0; 112 } 113 LCRYPTO_ALIAS(X509_get_signature_info); 114