| 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 |