untrusted comment: verify with openbsd-67-base.pub RWRmkIA877Io3kotfWKH9A+AjlI9lnMrw7ns8AG5tRm2aOYGBMgAkuG/SXVjNXcCrpVQ699biR1R3b1YtJul20yQsdRIKAH+xwA= OpenBSD 6.7 errata 031, December 8, 2020: Malformed ASN.1 in a certificate revocation list or a timestamp response token can lead to a NULL pointer dereference. Apply by doing: signify -Vep /etc/signify/openbsd-67-base.pub -x 031_asn1.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install libcrypto, isakmpd and unwind: cd /usr/src/lib/libcrypto make obj make includes make make install cd /usr/src/sbin/isakmpd make obj make make install cd /usr/src/sbin/unwind make obj make make install Index: lib/libcrypto/asn1/asn1.h =================================================================== RCS file: /cvs/src/lib/libcrypto/asn1/asn1.h,v retrieving revision 1.53 diff -u -p -r1.53 asn1.h --- lib/libcrypto/asn1/asn1.h 30 Nov 2018 04:51:19 -0000 1.53 +++ lib/libcrypto/asn1/asn1.h 3 Dec 2020 19:20:57 -0000 @@ -1137,6 +1137,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_BAD_OBJECT_HEADER 102 #define ASN1_R_BAD_PASSWORD_READ 103 #define ASN1_R_BAD_TAG 104 +#define ASN1_R_BAD_TEMPLATE 230 #define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214 #define ASN1_R_BN_LIB 105 #define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 Index: lib/libcrypto/asn1/asn1_err.c =================================================================== RCS file: /cvs/src/lib/libcrypto/asn1/asn1_err.c,v retrieving revision 1.21 diff -u -p -r1.21 asn1_err.c --- lib/libcrypto/asn1/asn1_err.c 29 Mar 2018 02:29:24 -0000 1.21 +++ lib/libcrypto/asn1/asn1_err.c 3 Dec 2020 19:20:57 -0000 @@ -85,6 +85,7 @@ static ERR_STRING_DATA ASN1_str_reasons[ {ERR_REASON(ASN1_R_BAD_OBJECT_HEADER) , "bad object header"}, {ERR_REASON(ASN1_R_BAD_PASSWORD_READ) , "bad password read"}, {ERR_REASON(ASN1_R_BAD_TAG) , "bad tag"}, + {ERR_REASON(ASN1_R_BAD_TEMPLATE) , "bad template"}, {ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH), "bmpstring is wrong length"}, {ERR_REASON(ASN1_R_BN_LIB) , "bn lib"}, {ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "boolean is wrong length"}, Index: lib/libcrypto/asn1/asn1_lib.c =================================================================== RCS file: /cvs/src/lib/libcrypto/asn1/asn1_lib.c,v retrieving revision 1.44 diff -u -p -r1.44 asn1_lib.c --- lib/libcrypto/asn1/asn1_lib.c 17 Nov 2018 09:34:11 -0000 1.44 +++ lib/libcrypto/asn1/asn1_lib.c 3 Dec 2020 19:20:57 -0000 @@ -388,6 +388,8 @@ ASN1_STRING_cmp(const ASN1_STRING *a, co { int i; + if (a == NULL || b == NULL) + return -1; i = (a->length - b->length); if (i == 0) { i = memcmp(a->data, b->data, a->length); Index: lib/libcrypto/asn1/tasn_dec.c =================================================================== RCS file: /cvs/src/lib/libcrypto/asn1/tasn_dec.c,v retrieving revision 1.37 diff -u -p -r1.37 tasn_dec.c --- lib/libcrypto/asn1/tasn_dec.c 1 Apr 2019 15:48:04 -0000 1.37 +++ lib/libcrypto/asn1/tasn_dec.c 3 Dec 2020 19:20:57 -0000 @@ -210,6 +210,16 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, cons break; case ASN1_ITYPE_MSTRING: + /* + * It never makes sense for multi-strings to have implicit + * tagging, so if tag != -1, then this looks like an error in + * the template. + */ + if (tag != -1) { + ASN1error(ASN1_R_BAD_TEMPLATE); + goto err; + } + p = *in; /* Just read in tag and class */ ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, @@ -245,6 +255,16 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, cons it, tag, aclass, opt, ctx); case ASN1_ITYPE_CHOICE: + /* + * It never makes sense for CHOICE types to have implicit + * tagging, so if tag != -1, then this looks like an error in + * the template. + */ + if (tag != -1) { + ASN1error(ASN1_R_BAD_TEMPLATE); + goto err; + } + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) goto auxerr; Index: lib/libcrypto/asn1/tasn_enc.c =================================================================== RCS file: /cvs/src/lib/libcrypto/asn1/tasn_enc.c,v retrieving revision 1.22 diff -u -p -r1.22 tasn_enc.c --- lib/libcrypto/asn1/tasn_enc.c 1 Apr 2019 15:48:04 -0000 1.22 +++ lib/libcrypto/asn1/tasn_enc.c 3 Dec 2020 19:20:57 -0000 @@ -61,6 +61,7 @@ #include #include +#include #include static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, @@ -152,9 +153,27 @@ ASN1_item_ex_i2d(ASN1_VALUE **pval, unsi break; case ASN1_ITYPE_MSTRING: + /* + * It never makes sense for multi-strings to have implicit + * tagging, so if tag != -1, then this looks like an error in + * the template. + */ + if (tag != -1) { + ASN1error(ASN1_R_BAD_TEMPLATE); + return 0; + } return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); case ASN1_ITYPE_CHOICE: + /* + * It never makes sense for CHOICE types to have implicit + * tagging, so if tag != -1, then this looks like an error in + * the template. + */ + if (tag != -1) { + ASN1error(ASN1_R_BAD_TEMPLATE); + return 0; + } if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) return 0; i = asn1_get_choice_selector(pval, it); Index: lib/libcrypto/x509v3/v3_genn.c =================================================================== RCS file: /cvs/src/lib/libcrypto/x509v3/Attic/v3_genn.c,v retrieving revision 1.12 diff -u -p -r1.12 v3_genn.c --- lib/libcrypto/x509v3/v3_genn.c 26 Sep 2015 17:38:41 -0000 1.12 +++ lib/libcrypto/x509v3/v3_genn.c 3 Dec 2020 19:21:06 -0000 @@ -117,16 +117,17 @@ OTHERNAME_free(OTHERNAME *a) ASN1_item_free((ASN1_VALUE *)a, &OTHERNAME_it); } +/* Uses explicit tagging since DIRECTORYSTRING is a CHOICE type */ static const ASN1_TEMPLATE EDIPARTYNAME_seq_tt[] = { { - .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, .tag = 0, .offset = offsetof(EDIPARTYNAME, nameAssigner), .field_name = "nameAssigner", .item = &DIRECTORYSTRING_it, }, { - .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .flags = ASN1_TFLG_EXPLICIT, .tag = 1, .offset = offsetof(EDIPARTYNAME, partyName), .field_name = "partyName", @@ -324,6 +325,37 @@ GENERAL_NAME_dup(GENERAL_NAME *a) return ASN1_item_dup(&GENERAL_NAME_it, a); } +static int +EDIPARTYNAME_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) +{ + int res; + + /* + * Shouldn't be possible in a valid GENERAL_NAME, but we handle it + * anyway. OTHERNAME_cmp treats NULL != NULL, so we do the same here. + */ + if (a == NULL || b == NULL) + return -1; + if (a->nameAssigner == NULL && b->nameAssigner != NULL) + return -1; + if (a->nameAssigner != NULL && b->nameAssigner == NULL) + return 1; + /* If we get here, both have nameAssigner set or both unset. */ + if (a->nameAssigner != NULL) { + res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner); + if (res != 0) + return res; + } + /* + * partyName is required, so these should never be NULL. We treat it in + * the same way as the a == NULL || b == NULL case above. + */ + if (a->partyName == NULL || b->partyName == NULL) + return -1; + + return ASN1_STRING_cmp(a->partyName, b->partyName); +} + /* Returns 0 if they are equal, != 0 otherwise. */ int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) @@ -334,8 +366,11 @@ GENERAL_NAME_cmp(GENERAL_NAME *a, GENERA return -1; switch (a->type) { case GEN_X400: + result = ASN1_TYPE_cmp(a->d.x400Address, b->d.x400Address); + break; + case GEN_EDIPARTY: - result = ASN1_TYPE_cmp(a->d.other, b->d.other); + result = EDIPARTYNAME_cmp(a->d.ediPartyName, b->d.ediPartyName); break; case GEN_OTHERNAME: @@ -384,8 +419,11 @@ GENERAL_NAME_set0_value(GENERAL_NAME *a, { switch (type) { case GEN_X400: + a->d.x400Address = value; + break; + case GEN_EDIPARTY: - a->d.other = value; + a->d.ediPartyName = value; break; case GEN_OTHERNAME: @@ -420,8 +458,10 @@ GENERAL_NAME_get0_value(GENERAL_NAME *a, *ptype = a->type; switch (a->type) { case GEN_X400: + return a->d.x400Address; + case GEN_EDIPARTY: - return a->d.other; + return a->d.ediPartyName; case GEN_OTHERNAME: return a->d.otherName;