The old loop read one byte past the length. It also stopped the loop
too early on interior NUL. See also upstream's
https://github.com/openssl/openssl/pull/16433, though I've opted to
rewrite the function entirely rather than use their fix.
Also deduplicate the PrintableString check.
Change-Id: Ia8bd282047c2a2ed1d5e71a68a3947c7c108df95
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49066
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
strchr is interprets the trailing NUL as part of the string, so
is_printable thought NUL was allowed. Just write the code in the obvious
way and let the compiler figure it out. (It seems to make a clever
bitmask or something.)
Update-Note: ASN1_mbstring_ncopy will no longer allow PrintableString
for strings containing NUL.
Change-Id: I3675191ceb44c06f0ac7b430f88272cabf392d35
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49065
Reviewed-by: Adam Langley <agl@google.com>
I noticed this while I was reading through the encoder. OpenSSL's ASN.1
library is very sloppy when it comes to reusing enums. It has...
- Universal tag numbers. These are just tag numbers from ASN.1
- utype. These are used in the ASN1_TYPE type field, as well as the
ASN1_ITEM utype fields They are the same as universal tag numbers,
except non-universal types map to V_ASN1_OTHER. I believe ASN1_TYPE
types and ASN1_ITEM utypes are the same, but I am not positive.
- ASN1_STRING types. These are the same as utypes, except V_ASN1_OTHER
appears to only be possible when embedded inside ASN1_TYPE, and
negative INTEGER and ENUMERATED values get mapped to
V_ASN1_NEG_INTEGER and V_ASN1_NEG_ENUMERATED. Additionally, some
values like V_ASN1_OBJECT are possible in a utype but not possible in
an ASN1_STRING (and will cause lots of problems if ever placed in
one).
- Sometimes one of these enums is augmented with V_ASN1_UNDEF and/or
V_ASN1_APP_CHOOSE for extra behaviors.
- Probably others I'm missing.
These get mixed up all the time. asn1_ex_i2c's MSTRING path converts
from ASN1_STRING type to utype and forgets to normalize V_ASN1_NEG_*.
This means that negative INTEGERs and ENUMERATEDs in MSTRINGs do not get
encoded right.
The negative INTEGER case is unreachable (unless the caller passes
the wrong ASN1_STRING to an MSTRING i2d function, but mismatching i2d
functions generally does wrong things), but the negative ENUMERATED case
is reachable. Fix this and add a test.
Change-Id: I762d482e72ebf03fd64bba291e751ab0b51af2a9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48805
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
In writing the tests, I noticed that the documentation was wrong. First,
the maximum lengths are measured in codepoints, not bytes.
Second, the TODO was wrong. We actually do handle this correctly,
*almost*. Rather, the bug is that the function assumes |mask| contains
no extraneous bits. If it does, all extraneous bits are interpreted as
B_ASN1_UTF8STRING. This seems like a bug, so I've gone ahead and fixed
that, with a test.
Change-Id: I7ba8fa700a8e21e6d25cb7ce879dace685eecf7e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48825
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
ASN1_STRING and ASN1_TYPE type values almost line up, but not quite.
Negative INTEGERs are not possible in X509_NAME (tag2bit maps INTEGER to
0), but negative ENUMERATEDs are (tag2bit maps ENUMERATED to
B_ASN1_UNKNOWN). See https://crbug.com/boringssl/412 for some notes on
this mess. Either way, the library will freely produce ASN1_STRING
INTEGERs and ENUMERATEDs in non-MSTRING contexts, so get this case
right.
Change-Id: Ica537f4d683e7a6becc96e2eee3cb66e53372124
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48785
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
ASN1_STRING_print_ex is extremely complex and attempting to implement
RFC2253, so write some tests for it. Along the way, unexport
CHARTYPE_*, which are internal book-keeping used in
ASN1_STRING_print_ex.
Change-Id: Idb27cd40fb66dc099d1fd6d039a00404608c2063
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48776
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
They would previously output syntax errors.
Change-Id: I7817a91d0c8ed8d6ac6a5a1fd9c9ed1223c5960e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48667
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
We already had a test, but move it to asn1_test.cc since it's part of
the ASN.1 library. Also, since it's easy, test it using public APIs
rather than stack-allocating an ASN1_STRING.
Change-Id: Ic77494e6c8f74584d159a600e334416197761475
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48227
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
OpenSSL's BIT STRING representation has two modes, one where it
implicitly trims trailing zeros and the other where the number of unused
bits is explicitly set. This means logic in ASN1_item_verify, or
elsewhere in callers, that checks flags and ASN1_STRING_length is
inconsistent with i2c_ASN1_BIT_STRING.
Add ASN1_BIT_STRING_num_bytes for code that needs to deal with X.509
using BIT STRING for some fields instead of OCTET STRING. Switch
ASN1_item_verify to it. Some external code does this too, so export it
as public API.
This is mostly a theoretical issue. All parsed BIT STRINGS use explicit
byte strings, and there are no APIs (apart from not-yet-opaquified
structs) to specify the ASN1_STRING in X509, etc., structures. We
intentionally made X509_set1_signature_value, etc., internally construct
the ASN1_STRING. Still having an API is more consistent and helps nudge
callers towards rejecting excess bits when they want bytes.
It may also be worth a public API for consistently accessing the bit
count. I've left it alone for now because I've not seen callers that
need it, and it saves worrying about bytes-to-bits overflows.
This also fixes a bug in the original version of the truncating logic
when the entire string was all zeros, and const-corrects a few
parameters.
Change-Id: I9d29842a3d3264b0cde61ca8cfea07d02177dbc2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48225
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
(Imported from upstream's 65b88a75921533ada8b465bc8d5c0817ad927947 and
7c65179ad95d0f6f598ee82e763fce2567fe5802.)
Change-Id: Id6a9604231d3cacc5e20af07e40d09e20dc9d3c0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47332
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
The ASN1_BOOLEAN representation is a mess. ASN1_BOOLEAN is an int
and if non-negative (negative values mean omitted or default), gets cast
to uint8_t and encoded as the value. This means callers are simply
expected to know true is 0xff, not 1. Fix this by only encoding 0 or
0xff.
This also fixes a bug where values like 0x100 are interpreted as true
(e.g. in the tasn_enc.c logic to handle default values), but encoded as
false because the cast only looks at the least significant byte.
This CL does not change the parsing behavior, which is to allow any BER
encoding and preserve the value in the in-memory representation (though
we should tighten that). However the BER encode will no longer be
preserved when re-encoding.
Update-Note: Callers setting ASN1_BOOLEANs to a positive value other
than 0xff will now encode 0xff. This probably fixes a bug, but if anyone
was attaching significance to incorrectly-encoded booleans, that will
break.
Change-Id: I5bb53e068d5900daca07299a27c0551e78ffa91d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46924
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
This fixes a bug in ASN1_TYPE_get. Partly imported from upstream's
261ec72d58af64327214a78ca1c54b169ad93c28, though I don't believe
ASN1_TYPE_set was broken per se. There's also a lot more than in that
commit.
I've added a test to ensure we maintain the unused bits invariant
anyway, in case external code relies on it. (The invariant comes from
the pointer being NULL-initialized and from ASN1_primitive_free zeroing
*pval on free.)
Change-Id: I4c0c57519a7628041d81c26cd850317e01409556
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46324
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
This should fix the Chromium roll.
Windows shared library builds are fussy about dllexport vs. dllimport in
a way that's incompatible with external uses of the asn1t.h macros. The
issue is the DECLARE_* macros will add dllexport vs. dllimport on the
assumption the symbols are defined in libcrypto, but external
definitions need a different selector.
Rather than add more complex macros for this, just exclude those tests.
Ideally we wouldn't supoport asn1t.h outside the library at all, if we
can manage it, so no sense in trying to make it work.
This excludes both the new and the old tests. Although this has been
working thus far, it only works because we've been setting the
BORINGSSL_IMPLEMENTATION symbol for test targets wrong in Chromium. I'm
confused how that's been working at all (maybe dllexport vs. dllimport
is more lax when it comes to functions rather than variables?), but when
I do it correctly, the ASN1_LINKED_LIST template breaks too.
Change-Id: I391edba1748f66c383ed55a9d23053674bbb876e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44484
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
This imports 1ecc76f6746cefd502c7e9000bdfa4e5d7911386 and
41d62636fd996c031c0c7cef746476278583dc9e from upstream. These would have
rejected the mistake in OpenSSL's EDIPartyName sturcture.
Change-Id: I4eb218f9372bea0f7ff302321b9dc1992ef0c13a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44424
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
At one point in the SSLeay days, all the ASN1_STRING typedefs were
separate structs (but only in debug builds) and the M_ASN1_* macros
included type casts to handle this.
This is long gone, but we still have the M_ASN1_* macros. Remove the
casts and switch code within the library to call the macros. Some
subtleties:
- The "MSTRING" types (what OpenSSL calls its built-in CHOICEs
containing some set of string types) are weird because the M_FOO_new()
macro and the tasn_new.c FOO_new() function behave differently. I've
split those into a separate CL.
- ASN1_STRING_type, etc., call into the macro, which accesses the field
directly. This CL inverts the dependency.
- ASN1_INTEGER_new and ASN1_INTEGER_free, etc., are generated via
IMPLEMENT_ASN1_STRING_FUNCTIONS in tasn_typ.c. I've pointed
M_ASN1_INTEGER_new and M_ASN1_INTEGER_free to these fields. (The free
function is a no-op, but consistent.)
- The other macros like M_ASN1_BIT_STRING_dup largely do not have
corresponding functions. I've aligned with OpenSSL in just using the
generic ASN1_STRING_dup function. But some others, like
M_ASN1_OCTET_STRING_dup have a corresponding ASN1_OCTET_STRING_dup
function. OpenSSL retained these, so I have too.
Update-Note: Some external code uses the M_ASN1_* macros. This should
remain compatible, but some type errors may have gotten through
unnoticed. This CL restores type-checking.
Change-Id: I8656abc7d0f179192e05a852c97483c021ad9b20
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44045
Reviewed-by: Adam Langley <agl@google.com>