-# $OpenBSD: Makefile,v 1.202 2024/08/10 06:41:49 tb Exp $
+# $OpenBSD: Makefile,v 1.203 2024/08/28 07:15:04 tb Exp $
LIB= crypto
LIBREBUILD=y
SRCS+= x509_r2x.c
SRCS+= x509_req.c
SRCS+= x509_set.c
+SRCS+= x509_siginfo.c
SRCS+= x509_skey.c
SRCS+= x509_trs.c
SRCS+= x509_txt.c
-/* $OpenBSD: ecx_methods.c,v 1.13 2024/04/02 04:04:07 tb Exp $ */
+/* $OpenBSD: ecx_methods.c,v 1.14 2024/08/28 07:15:04 tb Exp $ */
/*
* Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
*
return 0;
}
+static int
+ecx_signature_info(const X509_ALGOR *algor, int *md_nid, int *pkey_nid,
+ int *security_bits, uint32_t *flags)
+{
+ const ASN1_OBJECT *aobj;
+
+ X509_ALGOR_get0(&aobj, NULL, NULL, algor);
+ if (OBJ_obj2nid(aobj) != EVP_PKEY_ED25519)
+ return 0;
+
+ *md_nid = NID_undef;
+ *pkey_nid = NID_ED25519;
+ *security_bits = ED25519_SECURITY_BITS;
+ *flags = X509_SIG_INFO_TLS | X509_SIG_INFO_VALID;
+
+ return 1;
+}
+
static int
ecx_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
{
.pkey_bits = ecx_bits,
.pkey_security_bits = ecx_security_bits,
+ .signature_info = ecx_signature_info,
+
.param_cmp = ecx_param_cmp,
.pkey_free = ecx_free,
-/* $OpenBSD: evp_local.h,v 1.23 2024/08/22 12:24:24 tb Exp $ */
+/* $OpenBSD: evp_local.h,v 1.24 2024/08/28 07:15:04 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
int (*pkey_bits)(const EVP_PKEY *pk);
int (*pkey_security_bits)(const EVP_PKEY *pk);
+ int (*signature_info)(const X509_ALGOR *sig_alg, int *out_md_nid,
+ int *out_pkey_nid, int *out_security_bits, uint32_t *out_flags);
+
int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder,
int derlen);
int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder);
-/* $OpenBSD: rsa_ameth.c,v 1.58 2024/03/17 07:10:00 tb Exp $ */
+/* $OpenBSD: rsa_ameth.c,v 1.59 2024/08/28 07:15:04 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
return 1;
}
+static int
+rsa_pss_signature_info(const X509_ALGOR *alg, int *out_md_nid,
+ int *out_pkey_nid, int *out_security_bits, uint32_t *out_flags)
+{
+ RSA_PSS_PARAMS *pss = NULL;
+ const ASN1_OBJECT *aobj;
+ const EVP_MD *md, *mgf1md;
+ int md_len, salt_len;
+ int md_nid = NID_undef, pkey_nid = NID_undef;
+ int security_bits = -1;
+ uint32_t flags = 0;
+
+ X509_ALGOR_get0(&aobj, NULL, NULL, alg);
+ if (OBJ_obj2nid(aobj) != EVP_PKEY_RSA_PSS)
+ goto err;
+
+ if ((pss = rsa_pss_decode(alg)) == NULL)
+ goto err;
+ if (!rsa_pss_get_param(pss, &md, &mgf1md, &salt_len))
+ goto err;
+
+ if ((md_nid = EVP_MD_type(md)) == NID_undef)
+ goto err;
+ if ((md_len = EVP_MD_size(md)) <= 0)
+ goto err;
+
+ /*
+ * RFC 8446, section 4.2.3 - restricts the digest algorithm:
+ * - it must be one of SHA256, SHA384, and SHA512;
+ * - the same digest must be used in the mask generation function;
+ * - the salt length must match the output length of the digest.
+ * XXX - consider separate flags for these checks.
+ */
+ if (md_nid == NID_sha256 || md_nid == NID_sha384 || md_nid == NID_sha512) {
+ if (md_nid == EVP_MD_type(mgf1md) && salt_len == md_len)
+ flags |= X509_SIG_INFO_TLS;
+ }
+
+ security_bits = md_len * 4;
+ flags |= X509_SIG_INFO_VALID;
+
+ *out_md_nid = md_nid;
+ *out_pkey_nid = pkey_nid;
+ *out_security_bits = security_bits;
+ *out_flags = flags;
+
+ err:
+ RSA_PSS_PARAMS_free(pss);
+
+ return (flags & X509_SIG_INFO_VALID) != 0;
+}
+
#ifndef OPENSSL_NO_CMS
static int
rsa_cms_verify(CMS_SignerInfo *si)
.pkey_bits = rsa_bits,
.pkey_security_bits = rsa_security_bits,
+ .signature_info = rsa_pss_signature_info,
+
.sig_print = rsa_sig_print,
.pkey_free = rsa_free,
-/* $OpenBSD: x509.h,v 1.112 2024/06/12 03:55:46 tb Exp $ */
+/* $OpenBSD: x509.h,v 1.113 2024/08/28 07:15:04 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
int i2d_re_X509_tbs(X509 *x, unsigned char **pp);
+#if defined(LIBRESSL_INTERNAL) || defined(LIBRESSL_NEXT_API)
+/* Flags returned by X509_get_signature_info(): valid and suitable for TLS. */
+#define X509_SIG_INFO_VALID 1
+#define X509_SIG_INFO_TLS 2
+int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
+ uint32_t *flags);
+#endif
+
void X509_get0_signature(const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg, const X509 *x);
int X509_get_signature_nid(const X509 *x);
--- /dev/null
+/* $OpenBSD: x509_siginfo.c,v 1.1 2024/08/28 07:15:04 tb Exp $ */
+
+/*
+ * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+
+#include "evp_local.h"
+
+#include "x509_internal.h"
+
+static int
+x509_find_sigid_algs(const X509 *x509, int *out_md_nid, int *out_pkey_nid)
+{
+ const ASN1_OBJECT *aobj;
+ int nid;
+
+ *out_md_nid = NID_undef;
+ *out_pkey_nid = NID_undef;
+
+ X509_ALGOR_get0(&aobj, NULL, NULL, x509->sig_alg);
+ if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
+ return 0;
+
+ return OBJ_find_sigid_algs(nid, out_md_nid, out_pkey_nid);
+}
+
+int
+X509_get_signature_info(X509 *x509, int *out_md_nid, int *out_pkey_nid,
+ int *out_security_bits, uint32_t *out_flags)
+{
+ const EVP_MD *md;
+ int md_nid = NID_undef, pkey_nid = NID_undef, security_bits = -1;
+ uint32_t flags = 0;
+
+ if (out_md_nid != NULL)
+ *out_md_nid = md_nid;
+ if (out_pkey_nid != NULL)
+ *out_pkey_nid = pkey_nid;
+ if (out_security_bits != NULL)
+ *out_security_bits = security_bits;
+ if (out_flags != NULL)
+ *out_flags = flags;
+
+ if (!x509v3_cache_extensions(x509))
+ goto err;
+
+ if (!x509_find_sigid_algs(x509, &md_nid, &pkey_nid))
+ goto err;
+
+ /*
+ * If md_nid == NID_undef, this means we need to consult the ameth.
+ * Handlers are available for EdDSA and RSA-PSS. No other signature
+ * algorithm with NID_undef should appear in a certificate.
+ */
+ if (md_nid == NID_undef) {
+ const EVP_PKEY_ASN1_METHOD *ameth;
+
+ if ((ameth = EVP_PKEY_asn1_find(NULL, pkey_nid)) == NULL ||
+ ameth->signature_info == NULL)
+ goto err;
+
+ if (!ameth->signature_info(x509->sig_alg, &md_nid, &pkey_nid,
+ &security_bits, &flags))
+ goto err;
+
+ goto done;
+ }
+
+ /* XXX - OpenSSL 3 special cases SHA-1 (63 bits) and MD5 (39 bits). */
+ if ((md = EVP_get_digestbynid(md_nid)) == NULL)
+ goto err;
+
+ /* Assume 4 bits of collision resistance per octet. */
+ if ((security_bits = EVP_MD_size(md)) <= 0)
+ goto err;
+ security_bits *= 4;
+
+ if (md_nid == NID_sha1 || md_nid == NID_sha256 ||
+ md_nid == NID_sha384 || md_nid == NID_sha512)
+ flags |= X509_SIG_INFO_TLS;
+
+ flags |= X509_SIG_INFO_VALID;
+
+ done:
+ if (out_md_nid != NULL)
+ *out_md_nid = md_nid;
+ if (out_pkey_nid != NULL)
+ *out_pkey_nid = pkey_nid;
+ if (out_security_bits != NULL)
+ *out_security_bits = security_bits;
+ if (out_flags != NULL)
+ *out_flags = flags;
+
+ err:
+ return (flags & X509_SIG_INFO_VALID) != 0;
+}
+LCRYPTO_ALIAS(X509_get_signature_info);