diff options
| author | tb <> | 2025-12-21 07:14:47 +0000 |
|---|---|---|
| committer | tb <> | 2025-12-21 07:14:47 +0000 |
| commit | f6a49b32fda99b726ad5b4434bcade613dccf49e (patch) | |
| tree | 0c1d11bfbfc0e5a5ef4e43b8e2b2f81f56cda4ff /src/usr.bin/openssl | |
| parent | 6ed4f26853f67c46fbd8cc721454414ad7318eae (diff) | |
| download | openbsd-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.c | 68 |
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 | ||
| 1655 | static int | 1655 | static int |
| 1656 | is_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 | */ | ||
| 1678 | static int | ||
| 1679 | validate_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 | |||
| 1703 | static int | ||
| 1656 | do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, | 1704 | do_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); |
