OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 /* | 5 /* |
6 Optimized ASN.1 DER decoder | 6 Optimized ASN.1 DER decoder |
7 | 7 |
8 */ | 8 */ |
9 | 9 |
10 #include "secerr.h" | 10 #include "secerr.h" |
11 #include "secasn1.h" /* for SEC_ASN1GetSubtemplate */ | 11 #include "secasn1.h" /* for SEC_ASN1GetSubtemplate */ |
12 #include "secitem.h" | 12 #include "secitem.h" |
13 | 13 |
14 /* | 14 /* |
15 * simple definite-length ASN.1 decoder | 15 * simple definite-length ASN.1 decoder |
16 */ | 16 */ |
17 | 17 |
18 static unsigned char* definite_length_decoder(const unsigned char *buf, | 18 static unsigned char* definite_length_decoder(const unsigned char *buf, |
19 const unsigned int length, | 19 const unsigned int buf_length, |
20 unsigned int *data_length, | 20 unsigned int *out_data_length, |
21 PRBool includeTag) | 21 PRBool includeTag) |
22 { | 22 { |
23 unsigned char tag; | 23 unsigned char tag; |
24 unsigned int used_length= 0; | 24 unsigned int used_length = 0; |
25 unsigned int data_len; | 25 unsigned int data_length = 0; |
| 26 unsigned char length_field_len = 0; |
| 27 unsigned char byte; |
| 28 unsigned int i; |
26 | 29 |
27 if (used_length >= length) | 30 if (used_length >= buf_length) |
28 { | 31 { |
| 32 /* Tag field was not found! */ |
29 return NULL; | 33 return NULL; |
30 } | 34 } |
31 tag = buf[used_length++]; | 35 tag = buf[used_length++]; |
32 | 36 |
33 /* blow out when we come to the end */ | |
34 if (tag == 0) | 37 if (tag == 0) |
35 { | 38 { |
| 39 /* End-of-contents octects should not be present in DER because |
| 40 DER doesn't use the indefinite length form. */ |
36 return NULL; | 41 return NULL; |
37 } | 42 } |
38 | 43 |
39 if (used_length >= length) | 44 if ((tag & 0x1F) == 0x1F) |
40 { | 45 { |
| 46 /* High tag number (a tag number > 30) is not supported */ |
41 return NULL; | 47 return NULL; |
42 } | 48 } |
43 data_len = buf[used_length++]; | |
44 | 49 |
45 if (data_len&0x80) | 50 if (used_length >= buf_length) |
46 { | 51 { |
47 int len_count = data_len & 0x7f; | 52 /* Length field was not found! */ |
| 53 return NULL; |
| 54 } |
| 55 byte = buf[used_length++]; |
48 | 56 |
49 data_len = 0; | 57 if (!(byte & 0x80)) |
| 58 { |
| 59 /* Short form: The high bit is not set. */ |
| 60 data_length = byte; /* clarity; we're returning a 32-bit int. */ |
| 61 } |
| 62 else |
| 63 { |
| 64 /* Long form. Extract the field length */ |
| 65 length_field_len = byte & 0x7F; |
| 66 if (length_field_len == 0) |
| 67 { |
| 68 /* DER doesn't use the indefinite length form. */ |
| 69 return NULL; |
| 70 } |
50 | 71 |
51 while (len_count-- > 0) | 72 if (length_field_len > sizeof(data_length)) |
52 { | 73 { |
53 if (used_length >= length) | 74 /* We don't support an extended length field longer than |
| 75 4 bytes (2^32) */ |
| 76 return NULL; |
| 77 } |
| 78 |
| 79 if (length_field_len > (buf_length - used_length)) |
| 80 { |
| 81 /* Extended length field was not found */ |
| 82 return NULL; |
| 83 } |
| 84 |
| 85 /* Iterate across the extended length field */ |
| 86 for (i = 0; i < length_field_len; i++) |
| 87 { |
| 88 byte = buf[used_length++]; |
| 89 data_length = (data_length << 8) | byte; |
| 90 |
| 91 if (i == 0) |
54 { | 92 { |
55 return NULL; | 93 PRBool too_long = PR_FALSE; |
| 94 if (length_field_len == 1) |
| 95 { |
| 96 too_long = ((byte & 0x80) == 0); /* Short form suffices */ |
| 97 } |
| 98 else |
| 99 { |
| 100 too_long = (byte == 0); /* This zero byte can be omitted */ |
| 101 } |
| 102 if (too_long) |
| 103 { |
| 104 /* The length is longer than needed. */ |
| 105 return NULL; |
| 106 } |
56 } | 107 } |
57 data_len = (data_len << 8) | buf[used_length++]; | |
58 } | 108 } |
59 } | 109 } |
60 | 110 |
61 if (data_len > (length-used_length) ) | 111 if (data_length > (buf_length - used_length)) |
62 { | 112 { |
| 113 /* The decoded length exceeds the available buffer */ |
63 return NULL; | 114 return NULL; |
64 } | 115 } |
65 if (includeTag) data_len += used_length; | |
66 | 116 |
67 *data_length = data_len; | 117 if (includeTag) |
| 118 { |
| 119 data_length += used_length; |
| 120 } |
| 121 |
| 122 *out_data_length = data_length; |
68 return ((unsigned char*)buf + (includeTag ? 0 : used_length)); | 123 return ((unsigned char*)buf + (includeTag ? 0 : used_length)); |
69 } | 124 } |
70 | 125 |
71 static SECStatus GetItem(SECItem* src, SECItem* dest, PRBool includeTag) | 126 static SECStatus GetItem(SECItem* src, SECItem* dest, PRBool includeTag) |
72 { | 127 { |
73 if ( (!src) || (!dest) || (!src->data && src->len) ) | 128 if ( (!src) || (!dest) || (!src->data && src->len) ) |
74 { | 129 { |
75 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 130 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
76 return SECFailure; | 131 return SECFailure; |
77 } | 132 } |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
888 if (SECSuccess == rv && newsrc.len) | 943 if (SECSuccess == rv && newsrc.len) |
889 { | 944 { |
890 rv = SECFailure; | 945 rv = SECFailure; |
891 PORT_SetError(SEC_ERROR_EXTRA_INPUT); | 946 PORT_SetError(SEC_ERROR_EXTRA_INPUT); |
892 } | 947 } |
893 } | 948 } |
894 | 949 |
895 return rv; | 950 return rv; |
896 } | 951 } |
897 | 952 |
OLD | NEW |