Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: net/der/parse_values.cc

Issue 1295943002: Add a function for validating a DER-encoded INTEGER. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cert_parsing
Patch Set: address comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/logging.h" 5 #include "base/logging.h"
6 #include "base/numerics/safe_math.h" 6 #include "base/numerics/safe_math.h"
7 #include "net/der/parse_values.h" 7 #include "net/der/parse_values.h"
8 8
9 namespace net { 9 namespace net {
10 10
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 } 118 }
119 119
120 // BER interprets any non-zero value as true, while DER requires a bool to 120 // BER interprets any non-zero value as true, while DER requires a bool to
121 // have either all bits zero (false) or all bits one (true). To support 121 // have either all bits zero (false) or all bits one (true). To support
122 // malformed certs, we recognized the BER encoding instead of failing to 122 // malformed certs, we recognized the BER encoding instead of failing to
123 // parse. 123 // parse.
124 bool ParseBoolRelaxed(const Input& in, bool* out) { 124 bool ParseBoolRelaxed(const Input& in, bool* out) {
125 return ParseBoolInternal(in, out, true /* relaxed */); 125 return ParseBoolInternal(in, out, true /* relaxed */);
126 } 126 }
127 127
128 bool ParseUint64(const Input& in, uint64_t* out) { 128 // ITU-T X.690 section 8.3.2 specifies that an integer value must be encoded
129 ByteReader reader(in); 129 // in the smallest number of octets. If the encoding consists of more than
130 size_t bytes_read = 0; 130 // one octet, then the bits of the first octet and the most significant bit
131 uint8_t data; 131 // of the second octet must not be all zeroes or all ones.
132 uint64_t value = 0; 132 bool IsValidInteger(const Input& in,
133 // Note that for simplicity, this check only admits integers up to 2^63-1. 133 bool* out_negative,
134 if (in.Length() > sizeof(uint64_t) || in.Length() == 0) 134 size_t* out_numeric_length) {
135 return false; 135 der::ByteReader reader(in);
136 while (reader.ReadByte(&data)) { 136 uint8_t first_byte;
137 if (bytes_read == 0 && (data & 0x80)) { 137
138 return false; 138 if (!reader.ReadByte(&first_byte))
139 return false; // Empty inputs are not allowed.
140
141 size_t numeric_length = in.Length();
142
143 uint8_t second_byte;
144 if (reader.ReadByte(&second_byte)) {
145 if (first_byte == 0) {
146 // The first byte in this case doesn't contribute to the number's value
147 // (just used to determine the sign).
148 numeric_length -= 1;
139 } 149 }
140 value <<= 8; 150
141 value |= data; 151 if ((first_byte == 0x00 || first_byte == 0xFF) &&
142 bytes_read++; 152 (first_byte & 0x80) == (second_byte & 0x80)) {
143 } 153 // Not a minimal encoding.
144 // ITU-T X.690 section 8.3.2 specifies that an integer value must be encoded
145 // in the smallest number of octets. If the encoding consists of more than
146 // one octet, then the bits of the first octet and the most significant bit
147 // of the second octet must not be all zeroes or all ones.
148 // Because this function only parses unsigned integers, there's no need to
149 // check for the all ones case.
150 if (bytes_read > 1) {
151 ByteReader first_bytes_reader(in);
152 uint8_t first_byte;
153 uint8_t second_byte;
154 if (!first_bytes_reader.ReadByte(&first_byte) ||
155 !first_bytes_reader.ReadByte(&second_byte)) {
156 return false;
157 }
158 if (first_byte == 0 && !(second_byte & 0x80)) {
159 return false; 154 return false;
160 } 155 }
161 } 156 }
157
158 *out_negative = (first_byte & 0x80) == 0x80;
159 *out_numeric_length = numeric_length;
160 return true;
161 }
162
163 bool ParseUint64(const Input& in, uint64_t* out) {
164 // Reject non-minimally encoded numbers, negative numbers, and non-negative
165 // numbers that would overflow the output type.
166 bool negative;
167 size_t numeric_length;
168 if (!IsValidInteger(in, &negative, &numeric_length))
169 return false;
170 if (negative || numeric_length > sizeof(*out))
171 return false;
172
173 ByteReader reader(in);
174 uint8_t data;
175 uint64_t value = 0;
176
177 while (reader.ReadByte(&data)) {
178 value <<= 8;
179 value |= data;
180 }
162 *out = value; 181 *out = value;
163 return true; 182 return true;
164 } 183 }
165 184
166 BitString::BitString(const Input& bytes, uint8_t unused_bits) 185 BitString::BitString(const Input& bytes, uint8_t unused_bits)
167 : bytes_(bytes), unused_bits_(unused_bits) { 186 : bytes_(bytes), unused_bits_(unused_bits) {
168 DCHECK_LT(unused_bits, 8); 187 DCHECK_LT(unused_bits, 8);
169 DCHECK(unused_bits == 0 || bytes.Length() != 0); 188 DCHECK(unused_bits == 0 || bytes.Length() != 0);
170 } 189 }
171 190
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 return false; 326 return false;
308 if (!ValidateGeneralizedTime(time)) 327 if (!ValidateGeneralizedTime(time))
309 return false; 328 return false;
310 *value = time; 329 *value = time;
311 return true; 330 return true;
312 } 331 }
313 332
314 } // namespace der 333 } // namespace der
315 334
316 } // namespace net 335 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698