summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/asn1/tasn_dec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/asn1/tasn_dec.c')
-rw-r--r--src/lib/libcrypto/asn1/tasn_dec.c78
1 files changed, 67 insertions, 11 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c
index 2426cb6253..c22501fc63 100644
--- a/src/lib/libcrypto/asn1/tasn_dec.c
+++ b/src/lib/libcrypto/asn1/tasn_dec.c
@@ -66,6 +66,7 @@
66#include <openssl/err.h> 66#include <openssl/err.h>
67 67
68static int asn1_check_eoc(unsigned char **in, long len); 68static int asn1_check_eoc(unsigned char **in, long len);
69static int asn1_find_end(unsigned char **in, long len, char inf);
69static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass); 70static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass);
70static int collect_data(BUF_MEM *buf, unsigned char **p, long plen); 71static int collect_data(BUF_MEM *buf, unsigned char **p, long plen);
71static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst, 72static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst,
@@ -644,7 +645,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long inl
644 cont = *in; 645 cont = *in;
645 /* If indefinite length constructed find the real end */ 646 /* If indefinite length constructed find the real end */
646 if(inf) { 647 if(inf) {
647 if(!asn1_collect(NULL, &p, plen, inf, -1, -1)) goto err; 648 if(!asn1_find_end(&p, plen, inf)) goto err;
648 len = p - cont; 649 len = p - cont;
649 } else { 650 } else {
650 len = p - cont + plen; 651 len = p - cont + plen;
@@ -807,12 +808,66 @@ int asn1_ex_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char
807 return ret; 808 return ret;
808} 809}
809 810
811/* This function finds the end of an ASN1 structure when passed its maximum
812 * length, whether it is indefinite length and a pointer to the content.
813 * This is more efficient than calling asn1_collect because it does not
814 * recurse on each indefinite length header.
815 */
816
817static int asn1_find_end(unsigned char **in, long len, char inf)
818 {
819 int expected_eoc;
820 long plen;
821 unsigned char *p = *in, *q;
822 /* If not indefinite length constructed just add length */
823 if (inf == 0)
824 {
825 *in += len;
826 return 1;
827 }
828 expected_eoc = 1;
829 /* Indefinite length constructed form. Find the end when enough EOCs
830 * are found. If more indefinite length constructed headers
831 * are encountered increment the expected eoc count otherwise justi
832 * skip to the end of the data.
833 */
834 while (len > 0)
835 {
836 if(asn1_check_eoc(&p, len))
837 {
838 expected_eoc--;
839 if (expected_eoc == 0)
840 break;
841 len -= 2;
842 continue;
843 }
844 q = p;
845 /* Just read in a header: only care about the length */
846 if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
847 -1, 0, 0, NULL))
848 {
849 ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
850 return 0;
851 }
852 if (inf)
853 expected_eoc++;
854 else
855 p += plen;
856 len -= p - q;
857 }
858 if (expected_eoc)
859 {
860 ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC);
861 return 0;
862 }
863 *in = p;
864 return 1;
865 }
866
810/* This function collects the asn1 data from a constructred string 867/* This function collects the asn1 data from a constructred string
811 * type into a buffer. The values of 'in' and 'len' should refer 868 * type into a buffer. The values of 'in' and 'len' should refer
812 * to the contents of the constructed type and 'inf' should be set 869 * to the contents of the constructed type and 'inf' should be set
813 * if it is indefinite length. If 'buf' is NULL then we just want 870 * if it is indefinite length.
814 * to find the end of the current structure: useful for indefinite
815 * length constructed stuff.
816 */ 871 */
817 872
818static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass) 873static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass)
@@ -822,11 +877,6 @@ static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, in
822 char cst, ininf; 877 char cst, ininf;
823 p = *in; 878 p = *in;
824 inf &= 1; 879 inf &= 1;
825 /* If no buffer and not indefinite length constructed just pass over the encoded data */
826 if(!buf && !inf) {
827 *in += len;
828 return 1;
829 }
830 while(len > 0) { 880 while(len > 0) {
831 q = p; 881 q = p;
832 /* Check for EOC */ 882 /* Check for EOC */
@@ -845,9 +895,15 @@ static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, in
845 } 895 }
846 /* If indefinite length constructed update max length */ 896 /* If indefinite length constructed update max length */
847 if(cst) { 897 if(cst) {
848 if(!asn1_collect(buf, &p, plen, ininf, tag, aclass)) return 0; 898#ifdef OPENSSL_ALLOW_NESTED_ASN1_STRINGS
899 if (!asn1_collect(buf, &p, plen, ininf, tag, aclass))
900 return 0;
901#else
902 ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING);
903 return 0;
904#endif
849 } else { 905 } else {
850 if(!collect_data(buf, &p, plen)) return 0; 906 if(plen && !collect_data(buf, &p, plen)) return 0;
851 } 907 }
852 len -= p - q; 908 len -= p - q;
853 } 909 }