diff options
author | Pauli <paul.dale@oracle.com> | 2017-08-21 07:19:17 +1000 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2017-08-22 09:45:25 +1000 |
commit | a1df06b36347a31c17d09e6ca3e1464bdf7eb4d5 (patch) | |
tree | beb260df46896a5c8668dd7f64c5dcefe677b1e6 /crypto/asn1 | |
parent | 00dfbaad88a69ed8294d6039bf5f7d722f72bf39 (diff) |
This has been added to avoid the situation where some host ctype.h functions
return true for characters > 127. I.e. they are allowing extended ASCII
characters through which then cause problems. E.g. marking superscript '2' as
a number then causes the common (ch - '0') conversion to number to fail
miserably. Likewise letters with diacritical marks can also cause problems.
If a non-ASCII character set is being used (currently only EBCDIC), it is
adjusted for.
The implementation uses a single table with a bit for each of the defined
classes. These functions accept an int argument and fail for
values out of range or for characters outside of the ASCII set. They will
work for both signed and unsigned character inputs.
Reviewed-by: Andy Polyakov <appro@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4102)
Diffstat (limited to 'crypto/asn1')
-rw-r--r-- | crypto/asn1/a_gentm.c | 1 | ||||
-rw-r--r-- | crypto/asn1/a_mbstr.c | 68 | ||||
-rw-r--r-- | crypto/asn1/a_object.c | 6 | ||||
-rw-r--r-- | crypto/asn1/a_print.c | 22 | ||||
-rw-r--r-- | crypto/asn1/a_strnid.c | 1 | ||||
-rw-r--r-- | crypto/asn1/a_time.c | 14 | ||||
-rw-r--r-- | crypto/asn1/a_utctm.c | 1 | ||||
-rw-r--r-- | crypto/asn1/asn_mime.c | 40 | ||||
-rw-r--r-- | crypto/asn1/asn_moid.c | 10 | ||||
-rw-r--r-- | crypto/asn1/asn_mstbl.c | 3 | ||||
-rw-r--r-- | crypto/asn1/f_int.c | 17 | ||||
-rw-r--r-- | crypto/asn1/f_string.c | 20 |
12 files changed, 47 insertions, 156 deletions
diff --git a/crypto/asn1/a_gentm.c b/crypto/asn1/a_gentm.c index 4e2e815d27..d3878d6e57 100644 --- a/crypto/asn1/a_gentm.c +++ b/crypto/asn1/a_gentm.c @@ -13,7 +13,6 @@ #include <stdio.h> #include <time.h> -#include <ctype.h> #include "internal/cryptlib.h" #include <openssl/asn1.h> #include "asn1_locl.h" diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c index e644fe0542..949fe6c161 100644 --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -8,7 +8,7 @@ */ #include <stdio.h> -#include <ctype.h> +#include "internal/ctype.h" #include "internal/cryptlib.h" #include <openssl/asn1.h> @@ -22,8 +22,6 @@ static int cpy_asc(unsigned long value, void *arg); static int cpy_bmp(unsigned long value, void *arg); static int cpy_univ(unsigned long value, void *arg); static int cpy_utf8(unsigned long value, void *arg); -static int is_numeric(unsigned long value); -static int is_printable(unsigned long value); /* * These functions take a string in UTF8, ASCII or multibyte form and a mask @@ -271,13 +269,15 @@ static int out_utf8(unsigned long value, void *arg) static int type_str(unsigned long value, void *arg) { - unsigned long types; - types = *((unsigned long *)arg); - if ((types & B_ASN1_NUMERICSTRING) && !is_numeric(value)) + unsigned long types = *((unsigned long *)arg); + const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value); + + if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native) + || native == ' ')) types &= ~B_ASN1_NUMERICSTRING; - if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value)) + if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native)) types &= ~B_ASN1_PRINTABLESTRING; - if ((types & B_ASN1_IA5STRING) && (value > 127)) + if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native)) types &= ~B_ASN1_IA5STRING; if ((types & B_ASN1_T61STRING) && (value > 0xff)) types &= ~B_ASN1_T61STRING; @@ -341,55 +341,3 @@ static int cpy_utf8(unsigned long value, void *arg) *p += ret; return 1; } - -/* Return 1 if the character is permitted in a PrintableString */ -static int is_printable(unsigned long value) -{ - int ch; - if (value > 0x7f) - return 0; - ch = (int)value; - /* - * Note: we can't use 'isalnum' because certain accented characters may - * count as alphanumeric in some environments. - */ -#ifndef CHARSET_EBCDIC - if ((ch >= 'a') && (ch <= 'z')) - return 1; - if ((ch >= 'A') && (ch <= 'Z')) - return 1; - if ((ch >= '0') && (ch <= '9')) - return 1; - if ((ch == ' ') || strchr("'()+,-./:=?", ch)) - return 1; -#else /* CHARSET_EBCDIC */ - if ((ch >= os_toascii['a']) && (ch <= os_toascii['z'])) - return 1; - if ((ch >= os_toascii['A']) && (ch <= os_toascii['Z'])) - return 1; - if ((ch >= os_toascii['0']) && (ch <= os_toascii['9'])) - return 1; - if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch])) - return 1; -#endif /* CHARSET_EBCDIC */ - return 0; -} - -/* Return 1 if the character is a digit or space */ -static int is_numeric(unsigned long value) -{ - int ch; - if (value > 0x7f) - return 0; - ch = (int)value; -#ifndef CHARSET_EBCDIC - if (!isdigit(ch) && ch != ' ') - return 0; -#else - if (ch > os_toascii['9']) - return 0; - if (ch < os_toascii['0'] && ch != os_toascii[' ']) - return 0; -#endif - return 1; -} diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 5ae56a24ea..566d8b352c 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,7 +9,7 @@ #include <stdio.h> #include <limits.h> -#include <ctype.h> +#include "internal/ctype.h" #include "internal/cryptlib.h" #include <openssl/buffer.h> #include <openssl/asn1.h> @@ -85,7 +85,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) c = *(p++); if ((c == ' ') || (c == '.')) break; - if (!isdigit(c)) { + if (!ossl_isdigit(c)) { ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT); goto err; } diff --git a/crypto/asn1/a_print.c b/crypto/asn1/a_print.c index 1aafe7c839..ed72b51926 100644 --- a/crypto/asn1/a_print.c +++ b/crypto/asn1/a_print.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,7 @@ */ #include <stdio.h> -#include <ctype.h> +#include "internal/ctype.h" #include "internal/cryptlib.h" #include <openssl/asn1.h> @@ -25,24 +25,10 @@ int ASN1_PRINTABLE_type(const unsigned char *s, int len) while ((*s) && (len-- != 0)) { c = *(s++); -#ifndef CHARSET_EBCDIC - if (!(((c >= 'a') && (c <= 'z')) || - ((c >= 'A') && (c <= 'Z')) || - ((c >= '0') && (c <= '9')) || - (c == ' ') || (c == '\'') || - (c == '(') || (c == ')') || - (c == '+') || (c == ',') || - (c == '-') || (c == '.') || - (c == '/') || (c == ':') || (c == '=') || (c == '?'))) + if (!ossl_isasn1print(c)) ia5 = 1; - if (c & 0x80) + if (!ossl_isascii(c)) t61 = 1; -#else - if (!isalnum(c) && (c != ' ') && strchr("'()+,-./:=?", c) == NULL) - ia5 = 1; - if (os_toascii[c] & 0x80) - t61 = 1; -#endif } if (t61) return (V_ASN1_T61STRING); diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c index 04c77eb452..a7d6b0e3df 100644 --- a/crypto/asn1/a_strnid.c +++ b/crypto/asn1/a_strnid.c @@ -8,7 +8,6 @@ */ #include <stdio.h> -#include <ctype.h> #include "internal/cryptlib.h" #include <openssl/asn1.h> #include <openssl/objects.h> diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 507292b76e..cb19e8024a 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -16,7 +16,7 @@ #include <stdio.h> #include <time.h> -#include <ctype.h> +#include "internal/ctype.h" #include "internal/cryptlib.h" #include <openssl/asn1t.h> #include "asn1_locl.h" @@ -124,14 +124,14 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) i++; break; } - if (!isdigit(a[o])) + if (!ossl_isdigit(a[o])) goto err; n = a[o] - '0'; /* incomplete 2-digital number */ if (++o == l) goto err; - if (!isdigit(a[o])) + if (!ossl_isdigit(a[o])) goto err; n = (n * 10) + a[o] - '0'; /* no more bytes to read, but we haven't seen time-zone yet */ @@ -192,7 +192,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) if (++o == l) goto err; i = o; - while ((o < l) && isdigit(a[o])) + while ((o < l) && ossl_isdigit(a[o])) o++; /* Must have at least one digit after decimal point */ if (i == o) @@ -223,11 +223,11 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) if (o + 4 != l) goto err; for (i = end; i < end + 2; i++) { - if (!isdigit(a[o])) + if (!ossl_isdigit(a[o])) goto err; n = a[o] - '0'; o++; - if (!isdigit(a[o])) + if (!ossl_isdigit(a[o])) goto err; n = (n * 10) + a[o] - '0'; i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; @@ -489,7 +489,7 @@ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) if (tm->length > 15 && v[14] == '.') { f = &v[14]; f_len = 1; - while (14 + f_len < l && isdigit(f[f_len])) + while (14 + f_len < l && ossl_isdigit(f[f_len])) ++f_len; } diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c index b88aa4218e..b224991aa3 100644 --- a/crypto/asn1/a_utctm.c +++ b/crypto/asn1/a_utctm.c @@ -9,7 +9,6 @@ #include <stdio.h> #include <time.h> -#include <ctype.h> #include "internal/cryptlib.h" #include <openssl/asn1.h> #include "asn1_locl.h" diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c index d7ec801b1e..01638da127 100644 --- a/crypto/asn1/asn_mime.c +++ b/crypto/asn1/asn_mime.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,7 @@ */ #include <stdio.h> -#include <ctype.h> +#include "internal/ctype.h" #include "internal/cryptlib.h" #include <openssl/rand.h> #include <openssl/x509.h> @@ -634,7 +634,7 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) return NULL; while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { /* If whitespace at line start then continuation line */ - if (mhdr && isspace((unsigned char)linebuf[0])) + if (mhdr && ossl_isspace(linebuf[0])) state = MIME_NAME; else state = MIME_START; @@ -758,7 +758,7 @@ static char *strip_start(char *name) /* Else null string */ return NULL; } - if (!isspace((unsigned char)c)) + if (!ossl_isspace(c)) return p; } return NULL; @@ -779,7 +779,7 @@ static char *strip_end(char *name) *p = 0; return name; } - if (isspace((unsigned char)c)) + if (ossl_isspace(c)) *p = 0; else return name; @@ -791,29 +791,18 @@ static MIME_HEADER *mime_hdr_new(const char *name, const char *value) { MIME_HEADER *mhdr = NULL; char *tmpname = NULL, *tmpval = NULL, *p; - int c; if (name) { if ((tmpname = OPENSSL_strdup(name)) == NULL) return NULL; - for (p = tmpname; *p; p++) { - c = (unsigned char)*p; - if (isupper(c)) { - c = tolower(c); - *p = c; - } - } + for (p = tmpname; *p; p++) + *p = ossl_tolower(*p); } if (value) { if ((tmpval = OPENSSL_strdup(value)) == NULL) goto err; - for (p = tmpval; *p; p++) { - c = (unsigned char)*p; - if (isupper(c)) { - c = tolower(c); - *p = c; - } - } + for (p = tmpval; *p; p++) + *p = ossl_tolower(*p); } mhdr = OPENSSL_malloc(sizeof(*mhdr)); if (mhdr == NULL) @@ -834,19 +823,14 @@ static MIME_HEADER *mime_hdr_new(const char *name, const char *value) static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value) { char *tmpname = NULL, *tmpval = NULL, *p; - int c; MIME_PARAM *mparam = NULL; + if (name) { tmpname = OPENSSL_strdup(name); if (!tmpname) goto err; - for (p = tmpname; *p; p++) { - c = (unsigned char)*p; - if (isupper(c)) { - c = tolower(c); - *p = c; - } - } + for (p = tmpname; *p; p++) + *p = ossl_tolower(*p); } if (value) { tmpval = OPENSSL_strdup(value); diff --git a/crypto/asn1/asn_moid.c b/crypto/asn1/asn_moid.c index 8176b76008..ed8517c372 100644 --- a/crypto/asn1/asn_moid.c +++ b/crypto/asn1/asn_moid.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,7 @@ */ #include <stdio.h> -#include <ctype.h> +#include "internal/ctype.h" #include <openssl/crypto.h> #include "internal/cryptlib.h" #include <openssl/conf.h> @@ -72,7 +72,7 @@ static int do_create(const char *value, const char *name) ostr = p + 1; if (!*ostr) return 0; - while (isspace((unsigned char)*ostr)) + while (ossl_isspace(*ostr)) ostr++; } @@ -83,10 +83,10 @@ static int do_create(const char *value, const char *name) if (p) { ln = value; - while (isspace((unsigned char)*ln)) + while (ossl_isspace(*ln)) ln++; p--; - while (isspace((unsigned char)*p)) { + while (ossl_isspace(*p)) { if (p == ln) return 0; p--; diff --git a/crypto/asn1/asn_mstbl.c b/crypto/asn1/asn_mstbl.c index 8260939002..ddcbcd07fe 100644 --- a/crypto/asn1/asn_mstbl.c +++ b/crypto/asn1/asn_mstbl.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,6 @@ */ #include <stdio.h> -#include <ctype.h> #include <openssl/crypto.h> #include "internal/cryptlib.h" #include <openssl/conf.h> diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c index ec556c92dc..ee035b72aa 100644 --- a/crypto/asn1/f_int.c +++ b/crypto/asn1/f_int.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,7 @@ */ #include <stdio.h> -#include <ctype.h> +#include "internal/ctype.h" #include "internal/cryptlib.h" #include <openssl/buffer.h> #include <openssl/asn1.h> @@ -76,18 +76,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) again = (buf[i - 1] == '\\'); for (j = 0; j < i; j++) { -#ifndef CHARSET_EBCDIC - if (!(((buf[j] >= '0') && (buf[j] <= '9')) || - ((buf[j] >= 'a') && (buf[j] <= 'f')) || - ((buf[j] >= 'A') && (buf[j] <= 'F')))) -#else - /* - * This #ifdef is not strictly necessary, since the characters - * A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but - * not the whole alphabet). Nevertheless, isxdigit() is faster. - */ - if (!isxdigit(buf[j])) -#endif + if (!ossl_isxdigit(buf[j])) { i = j; break; diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c index b9258bba8b..cfb895f247 100644 --- a/crypto/asn1/f_string.c +++ b/crypto/asn1/f_string.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,7 @@ */ #include <stdio.h> -#include <ctype.h> +#include "internal/ctype.h" #include "internal/cryptlib.h" #include <openssl/buffer.h> #include <openssl/asn1.h> @@ -47,7 +47,7 @@ int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) { - int i, j, k, m, n, again, bufsize, spec_char; + int i, j, k, m, n, again, bufsize; unsigned char *s = NULL, *sp; unsigned char *bufp; int num = 0, slen = 0, first = 1; @@ -74,19 +74,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) again = (buf[i - 1] == '\\'); for (j = i - 1; j > 0; j--) { -#ifndef CHARSET_EBCDIC - spec_char = (!(((buf[j] >= '0') && (buf[j] <= '9')) || - ((buf[j] >= 'a') && (buf[j] <= 'f')) || - ((buf[j] >= 'A') && (buf[j] <= 'F')))); -#else - /* - * This #ifdef is not strictly necessary, since the characters - * A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but - * not the whole alphabet). Nevertheless, isxdigit() is faster. - */ - spec_char = (!isxdigit(buf[j])); -#endif - if (spec_char) { + if (!ossl_isxdigit(buf[j])) { i = j; break; } |