summaryrefslogtreecommitdiff
path: root/src/usr.bin/openssl
diff options
context:
space:
mode:
authortb <>2025-12-21 07:14:47 +0000
committertb <>2025-12-21 07:14:47 +0000
commitf6a49b32fda99b726ad5b4434bcade613dccf49e (patch)
tree0c1d11bfbfc0e5a5ef4e43b8e2b2f81f56cda4ff /src/usr.bin/openssl
parent6ed4f26853f67c46fbd8cc721454414ad7318eae (diff)
downloadopenbsd-f6a49b32fda99b726ad5b4434bcade613dccf49e.tar.gz
openbsd-f6a49b32fda99b726ad5b4434bcade613dccf49e.tar.bz2
openbsd-f6a49b32fda99b726ad5b4434bcade613dccf49e.zip
Reimplement ASN1_PRINTABLE_type() dance in ca.c
In ca.c, there is some minimal validation of strings in the subject of a certificate. ASN1_PRINTABLE_type() is silly API that only exists for this one call. I want to remove a_print.c in the next major bump. ASN1_PRINTABLE_type() returns V_ASN1_PRINTABLESTRING if all characters belong to the specific subset of ASCII listed in X.680, 41.4, Table 10. Otherwise it returns V_ASN1_T61STRING or V_ASN1_IA5STRING depending on whether there is a character with the high bit set or not. With this in mind, the logic in ca.c comes down to this: blindly allow UTF-8, BMP and T61 strings. All other strings get rejected if the high bit of some character is set, or if the string is printable and there is a non-printable character. ok jsing kenjiro
Diffstat (limited to 'src/usr.bin/openssl')
-rw-r--r--src/usr.bin/openssl/ca.c68
1 files changed, 55 insertions, 13 deletions
diff --git a/src/usr.bin/openssl/ca.c b/src/usr.bin/openssl/ca.c
index 525596ae7c..a2e8a68368 100644
--- a/src/usr.bin/openssl/ca.c
+++ b/src/usr.bin/openssl/ca.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ca.c,v 1.63 2025/11/27 08:24:30 tb Exp $ */ 1/* $OpenBSD: ca.c,v 1.64 2025/12/21 07:14:47 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -1653,6 +1653,54 @@ certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1653} 1653}
1654 1654
1655static int 1655static int
1656is_printablestring_octet(const uint8_t u8)
1657{
1658 /*
1659 * X.680, 41.4, Table 10 lists the allowed characters in this order.
1660 */
1661
1662 if (u8 >= 'A' && u8 <= 'Z')
1663 return 1;
1664 if (u8 >= 'a' && u8 <= 'z')
1665 return 1;
1666 if (u8 >= '0' && u8 <= '9')
1667 return 1;
1668
1669 return u8 == ' ' || u8 == '\'' || u8 == '(' || u8 == ')' || u8 == '+' ||
1670 u8 == ',' || u8 == '-' || u8 == '.' || u8 == '/' || u8 == ':' ||
1671 u8 == '=' || u8 == '?';
1672}
1673
1674/*
1675 * Allows the high bit to be set only for UTF8, BMP and T61 strings, and
1676 * checks that a PrintableString only contains the specified characters.
1677 */
1678static int
1679validate_octets(const ASN1_STRING *astr)
1680{
1681 const uint8_t *buf = ASN1_STRING_get0_data(astr);
1682 int type = ASN1_STRING_type(astr);
1683 int i;
1684
1685 if (type == V_ASN1_BMPSTRING || type == V_ASN1_UTF8STRING ||
1686 type == V_ASN1_T61STRING)
1687 return 1;
1688
1689 for (i = 0; i < ASN1_STRING_length(astr); i++) {
1690 if (is_printablestring_octet(buf[i]))
1691 continue;
1692
1693 if (type == V_ASN1_PRINTABLESTRING)
1694 return 0;
1695
1696 if ((buf[i] & 0x80) != 0)
1697 return 0;
1698 }
1699
1700 return 1;
1701}
1702
1703static int
1656do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 1704do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1657 STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, 1705 STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy,
1658 CA_DB *db, BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, 1706 CA_DB *db, BIGNUM *serial, char *subj, unsigned long chtype, int multirdn,
@@ -1723,18 +1771,12 @@ do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1723 "\nemailAddress type needs to be of type IA5STRING\n"); 1771 "\nemailAddress type needs to be of type IA5STRING\n");
1724 goto err; 1772 goto err;
1725 } 1773 }
1726 if ((ASN1_STRING_type(str) != V_ASN1_BMPSTRING) && 1774
1727 (ASN1_STRING_type(str) != V_ASN1_UTF8STRING)) { 1775 if (!validate_octets(str)) {
1728 j = ASN1_PRINTABLE_type(ASN1_STRING_get0_data(str), 1776 BIO_printf(bio_err,
1729 ASN1_STRING_length(str)); 1777 "\nThe string contains characters that are illegal "
1730 if (((j == V_ASN1_T61STRING) && 1778 "for the ASN.1 type\n");
1731 (ASN1_STRING_type(str) != V_ASN1_T61STRING)) || 1779 goto err;
1732 ((j == V_ASN1_IA5STRING) &&
1733 (ASN1_STRING_type(str) == V_ASN1_PRINTABLESTRING))) {
1734 BIO_printf(bio_err,
1735 "\nThe string contains characters that are illegal for the ASN.1 type\n");
1736 goto err;
1737 }
1738 } 1780 }
1739 if (default_op) 1781 if (default_op)
1740 old_entry_print(bio_err, obj, str); 1782 old_entry_print(bio_err, obj, str);