1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (c) 2014, Google Inc.
2*8fb009dcSAndroid Build Coastguard Worker *
3*8fb009dcSAndroid Build Coastguard Worker * Permission to use, copy, modify, and/or distribute this software for any
4*8fb009dcSAndroid Build Coastguard Worker * purpose with or without fee is hereby granted, provided that the above
5*8fb009dcSAndroid Build Coastguard Worker * copyright notice and this permission notice appear in all copies.
6*8fb009dcSAndroid Build Coastguard Worker *
7*8fb009dcSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*8fb009dcSAndroid Build Coastguard Worker * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*8fb009dcSAndroid Build Coastguard Worker * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10*8fb009dcSAndroid Build Coastguard Worker * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*8fb009dcSAndroid Build Coastguard Worker * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12*8fb009dcSAndroid Build Coastguard Worker * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13*8fb009dcSAndroid Build Coastguard Worker * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14*8fb009dcSAndroid Build Coastguard Worker
15*8fb009dcSAndroid Build Coastguard Worker #include <openssl/asn1.h>
16*8fb009dcSAndroid Build Coastguard Worker #include <openssl/bytestring.h>
17*8fb009dcSAndroid Build Coastguard Worker #include <openssl/mem.h>
18*8fb009dcSAndroid Build Coastguard Worker
19*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
20*8fb009dcSAndroid Build Coastguard Worker #include <ctype.h>
21*8fb009dcSAndroid Build Coastguard Worker #include <inttypes.h>
22*8fb009dcSAndroid Build Coastguard Worker #include <string.h>
23*8fb009dcSAndroid Build Coastguard Worker
24*8fb009dcSAndroid Build Coastguard Worker #include "../asn1/internal.h"
25*8fb009dcSAndroid Build Coastguard Worker #include "../internal.h"
26*8fb009dcSAndroid Build Coastguard Worker #include "internal.h"
27*8fb009dcSAndroid Build Coastguard Worker
28*8fb009dcSAndroid Build Coastguard Worker
cbs_get(CBS * cbs,const uint8_t ** p,size_t n)29*8fb009dcSAndroid Build Coastguard Worker static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
30*8fb009dcSAndroid Build Coastguard Worker if (cbs->len < n) {
31*8fb009dcSAndroid Build Coastguard Worker return 0;
32*8fb009dcSAndroid Build Coastguard Worker }
33*8fb009dcSAndroid Build Coastguard Worker
34*8fb009dcSAndroid Build Coastguard Worker *p = cbs->data;
35*8fb009dcSAndroid Build Coastguard Worker cbs->data += n;
36*8fb009dcSAndroid Build Coastguard Worker cbs->len -= n;
37*8fb009dcSAndroid Build Coastguard Worker return 1;
38*8fb009dcSAndroid Build Coastguard Worker }
39*8fb009dcSAndroid Build Coastguard Worker
CBS_skip(CBS * cbs,size_t len)40*8fb009dcSAndroid Build Coastguard Worker int CBS_skip(CBS *cbs, size_t len) {
41*8fb009dcSAndroid Build Coastguard Worker const uint8_t *dummy;
42*8fb009dcSAndroid Build Coastguard Worker return cbs_get(cbs, &dummy, len);
43*8fb009dcSAndroid Build Coastguard Worker }
44*8fb009dcSAndroid Build Coastguard Worker
CBS_stow(const CBS * cbs,uint8_t ** out_ptr,size_t * out_len)45*8fb009dcSAndroid Build Coastguard Worker int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
46*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(*out_ptr);
47*8fb009dcSAndroid Build Coastguard Worker *out_ptr = NULL;
48*8fb009dcSAndroid Build Coastguard Worker *out_len = 0;
49*8fb009dcSAndroid Build Coastguard Worker
50*8fb009dcSAndroid Build Coastguard Worker if (cbs->len == 0) {
51*8fb009dcSAndroid Build Coastguard Worker return 1;
52*8fb009dcSAndroid Build Coastguard Worker }
53*8fb009dcSAndroid Build Coastguard Worker *out_ptr = OPENSSL_memdup(cbs->data, cbs->len);
54*8fb009dcSAndroid Build Coastguard Worker if (*out_ptr == NULL) {
55*8fb009dcSAndroid Build Coastguard Worker return 0;
56*8fb009dcSAndroid Build Coastguard Worker }
57*8fb009dcSAndroid Build Coastguard Worker *out_len = cbs->len;
58*8fb009dcSAndroid Build Coastguard Worker return 1;
59*8fb009dcSAndroid Build Coastguard Worker }
60*8fb009dcSAndroid Build Coastguard Worker
CBS_strdup(const CBS * cbs,char ** out_ptr)61*8fb009dcSAndroid Build Coastguard Worker int CBS_strdup(const CBS *cbs, char **out_ptr) {
62*8fb009dcSAndroid Build Coastguard Worker if (*out_ptr != NULL) {
63*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(*out_ptr);
64*8fb009dcSAndroid Build Coastguard Worker }
65*8fb009dcSAndroid Build Coastguard Worker *out_ptr = OPENSSL_strndup((const char*)cbs->data, cbs->len);
66*8fb009dcSAndroid Build Coastguard Worker return (*out_ptr != NULL);
67*8fb009dcSAndroid Build Coastguard Worker }
68*8fb009dcSAndroid Build Coastguard Worker
CBS_contains_zero_byte(const CBS * cbs)69*8fb009dcSAndroid Build Coastguard Worker int CBS_contains_zero_byte(const CBS *cbs) {
70*8fb009dcSAndroid Build Coastguard Worker return OPENSSL_memchr(cbs->data, 0, cbs->len) != NULL;
71*8fb009dcSAndroid Build Coastguard Worker }
72*8fb009dcSAndroid Build Coastguard Worker
CBS_mem_equal(const CBS * cbs,const uint8_t * data,size_t len)73*8fb009dcSAndroid Build Coastguard Worker int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
74*8fb009dcSAndroid Build Coastguard Worker if (len != cbs->len) {
75*8fb009dcSAndroid Build Coastguard Worker return 0;
76*8fb009dcSAndroid Build Coastguard Worker }
77*8fb009dcSAndroid Build Coastguard Worker return CRYPTO_memcmp(cbs->data, data, len) == 0;
78*8fb009dcSAndroid Build Coastguard Worker }
79*8fb009dcSAndroid Build Coastguard Worker
cbs_get_u(CBS * cbs,uint64_t * out,size_t len)80*8fb009dcSAndroid Build Coastguard Worker static int cbs_get_u(CBS *cbs, uint64_t *out, size_t len) {
81*8fb009dcSAndroid Build Coastguard Worker uint64_t result = 0;
82*8fb009dcSAndroid Build Coastguard Worker const uint8_t *data;
83*8fb009dcSAndroid Build Coastguard Worker
84*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get(cbs, &data, len)) {
85*8fb009dcSAndroid Build Coastguard Worker return 0;
86*8fb009dcSAndroid Build Coastguard Worker }
87*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < len; i++) {
88*8fb009dcSAndroid Build Coastguard Worker result <<= 8;
89*8fb009dcSAndroid Build Coastguard Worker result |= data[i];
90*8fb009dcSAndroid Build Coastguard Worker }
91*8fb009dcSAndroid Build Coastguard Worker *out = result;
92*8fb009dcSAndroid Build Coastguard Worker return 1;
93*8fb009dcSAndroid Build Coastguard Worker }
94*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u8(CBS * cbs,uint8_t * out)95*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u8(CBS *cbs, uint8_t *out) {
96*8fb009dcSAndroid Build Coastguard Worker const uint8_t *v;
97*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get(cbs, &v, 1)) {
98*8fb009dcSAndroid Build Coastguard Worker return 0;
99*8fb009dcSAndroid Build Coastguard Worker }
100*8fb009dcSAndroid Build Coastguard Worker *out = *v;
101*8fb009dcSAndroid Build Coastguard Worker return 1;
102*8fb009dcSAndroid Build Coastguard Worker }
103*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u16(CBS * cbs,uint16_t * out)104*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u16(CBS *cbs, uint16_t *out) {
105*8fb009dcSAndroid Build Coastguard Worker uint64_t v;
106*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_u(cbs, &v, 2)) {
107*8fb009dcSAndroid Build Coastguard Worker return 0;
108*8fb009dcSAndroid Build Coastguard Worker }
109*8fb009dcSAndroid Build Coastguard Worker *out = v;
110*8fb009dcSAndroid Build Coastguard Worker return 1;
111*8fb009dcSAndroid Build Coastguard Worker }
112*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u16le(CBS * cbs,uint16_t * out)113*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u16le(CBS *cbs, uint16_t *out) {
114*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u16(cbs, out)) {
115*8fb009dcSAndroid Build Coastguard Worker return 0;
116*8fb009dcSAndroid Build Coastguard Worker }
117*8fb009dcSAndroid Build Coastguard Worker *out = CRYPTO_bswap2(*out);
118*8fb009dcSAndroid Build Coastguard Worker return 1;
119*8fb009dcSAndroid Build Coastguard Worker }
120*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u24(CBS * cbs,uint32_t * out)121*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u24(CBS *cbs, uint32_t *out) {
122*8fb009dcSAndroid Build Coastguard Worker uint64_t v;
123*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_u(cbs, &v, 3)) {
124*8fb009dcSAndroid Build Coastguard Worker return 0;
125*8fb009dcSAndroid Build Coastguard Worker }
126*8fb009dcSAndroid Build Coastguard Worker *out = (uint32_t)v;
127*8fb009dcSAndroid Build Coastguard Worker return 1;
128*8fb009dcSAndroid Build Coastguard Worker }
129*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u32(CBS * cbs,uint32_t * out)130*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u32(CBS *cbs, uint32_t *out) {
131*8fb009dcSAndroid Build Coastguard Worker uint64_t v;
132*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_u(cbs, &v, 4)) {
133*8fb009dcSAndroid Build Coastguard Worker return 0;
134*8fb009dcSAndroid Build Coastguard Worker }
135*8fb009dcSAndroid Build Coastguard Worker *out = (uint32_t)v;
136*8fb009dcSAndroid Build Coastguard Worker return 1;
137*8fb009dcSAndroid Build Coastguard Worker }
138*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u32le(CBS * cbs,uint32_t * out)139*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u32le(CBS *cbs, uint32_t *out) {
140*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u32(cbs, out)) {
141*8fb009dcSAndroid Build Coastguard Worker return 0;
142*8fb009dcSAndroid Build Coastguard Worker }
143*8fb009dcSAndroid Build Coastguard Worker *out = CRYPTO_bswap4(*out);
144*8fb009dcSAndroid Build Coastguard Worker return 1;
145*8fb009dcSAndroid Build Coastguard Worker }
146*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u64(CBS * cbs,uint64_t * out)147*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u64(CBS *cbs, uint64_t *out) {
148*8fb009dcSAndroid Build Coastguard Worker return cbs_get_u(cbs, out, 8);
149*8fb009dcSAndroid Build Coastguard Worker }
150*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u64le(CBS * cbs,uint64_t * out)151*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u64le(CBS *cbs, uint64_t *out) {
152*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_u(cbs, out, 8)) {
153*8fb009dcSAndroid Build Coastguard Worker return 0;
154*8fb009dcSAndroid Build Coastguard Worker }
155*8fb009dcSAndroid Build Coastguard Worker *out = CRYPTO_bswap8(*out);
156*8fb009dcSAndroid Build Coastguard Worker return 1;
157*8fb009dcSAndroid Build Coastguard Worker }
158*8fb009dcSAndroid Build Coastguard Worker
CBS_get_last_u8(CBS * cbs,uint8_t * out)159*8fb009dcSAndroid Build Coastguard Worker int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
160*8fb009dcSAndroid Build Coastguard Worker if (cbs->len == 0) {
161*8fb009dcSAndroid Build Coastguard Worker return 0;
162*8fb009dcSAndroid Build Coastguard Worker }
163*8fb009dcSAndroid Build Coastguard Worker *out = cbs->data[cbs->len - 1];
164*8fb009dcSAndroid Build Coastguard Worker cbs->len--;
165*8fb009dcSAndroid Build Coastguard Worker return 1;
166*8fb009dcSAndroid Build Coastguard Worker }
167*8fb009dcSAndroid Build Coastguard Worker
CBS_get_bytes(CBS * cbs,CBS * out,size_t len)168*8fb009dcSAndroid Build Coastguard Worker int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
169*8fb009dcSAndroid Build Coastguard Worker const uint8_t *v;
170*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get(cbs, &v, len)) {
171*8fb009dcSAndroid Build Coastguard Worker return 0;
172*8fb009dcSAndroid Build Coastguard Worker }
173*8fb009dcSAndroid Build Coastguard Worker CBS_init(out, v, len);
174*8fb009dcSAndroid Build Coastguard Worker return 1;
175*8fb009dcSAndroid Build Coastguard Worker }
176*8fb009dcSAndroid Build Coastguard Worker
CBS_copy_bytes(CBS * cbs,uint8_t * out,size_t len)177*8fb009dcSAndroid Build Coastguard Worker int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
178*8fb009dcSAndroid Build Coastguard Worker const uint8_t *v;
179*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get(cbs, &v, len)) {
180*8fb009dcSAndroid Build Coastguard Worker return 0;
181*8fb009dcSAndroid Build Coastguard Worker }
182*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(out, v, len);
183*8fb009dcSAndroid Build Coastguard Worker return 1;
184*8fb009dcSAndroid Build Coastguard Worker }
185*8fb009dcSAndroid Build Coastguard Worker
cbs_get_length_prefixed(CBS * cbs,CBS * out,size_t len_len)186*8fb009dcSAndroid Build Coastguard Worker static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
187*8fb009dcSAndroid Build Coastguard Worker uint64_t len;
188*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_u(cbs, &len, len_len)) {
189*8fb009dcSAndroid Build Coastguard Worker return 0;
190*8fb009dcSAndroid Build Coastguard Worker }
191*8fb009dcSAndroid Build Coastguard Worker // If |len_len| <= 3 then we know that |len| will fit into a |size_t|, even on
192*8fb009dcSAndroid Build Coastguard Worker // 32-bit systems.
193*8fb009dcSAndroid Build Coastguard Worker assert(len_len <= 3);
194*8fb009dcSAndroid Build Coastguard Worker return CBS_get_bytes(cbs, out, len);
195*8fb009dcSAndroid Build Coastguard Worker }
196*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u8_length_prefixed(CBS * cbs,CBS * out)197*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
198*8fb009dcSAndroid Build Coastguard Worker return cbs_get_length_prefixed(cbs, out, 1);
199*8fb009dcSAndroid Build Coastguard Worker }
200*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u16_length_prefixed(CBS * cbs,CBS * out)201*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
202*8fb009dcSAndroid Build Coastguard Worker return cbs_get_length_prefixed(cbs, out, 2);
203*8fb009dcSAndroid Build Coastguard Worker }
204*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u24_length_prefixed(CBS * cbs,CBS * out)205*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
206*8fb009dcSAndroid Build Coastguard Worker return cbs_get_length_prefixed(cbs, out, 3);
207*8fb009dcSAndroid Build Coastguard Worker }
208*8fb009dcSAndroid Build Coastguard Worker
CBS_get_until_first(CBS * cbs,CBS * out,uint8_t c)209*8fb009dcSAndroid Build Coastguard Worker int CBS_get_until_first(CBS *cbs, CBS *out, uint8_t c) {
210*8fb009dcSAndroid Build Coastguard Worker const uint8_t *split = OPENSSL_memchr(CBS_data(cbs), c, CBS_len(cbs));
211*8fb009dcSAndroid Build Coastguard Worker if (split == NULL) {
212*8fb009dcSAndroid Build Coastguard Worker return 0;
213*8fb009dcSAndroid Build Coastguard Worker }
214*8fb009dcSAndroid Build Coastguard Worker return CBS_get_bytes(cbs, out, split - CBS_data(cbs));
215*8fb009dcSAndroid Build Coastguard Worker }
216*8fb009dcSAndroid Build Coastguard Worker
CBS_get_u64_decimal(CBS * cbs,uint64_t * out)217*8fb009dcSAndroid Build Coastguard Worker int CBS_get_u64_decimal(CBS *cbs, uint64_t *out) {
218*8fb009dcSAndroid Build Coastguard Worker uint64_t v = 0;
219*8fb009dcSAndroid Build Coastguard Worker int seen_digit = 0;
220*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(cbs) != 0) {
221*8fb009dcSAndroid Build Coastguard Worker uint8_t c = CBS_data(cbs)[0];
222*8fb009dcSAndroid Build Coastguard Worker if (!OPENSSL_isdigit(c)) {
223*8fb009dcSAndroid Build Coastguard Worker break;
224*8fb009dcSAndroid Build Coastguard Worker }
225*8fb009dcSAndroid Build Coastguard Worker CBS_skip(cbs, 1);
226*8fb009dcSAndroid Build Coastguard Worker if (// Forbid stray leading zeros.
227*8fb009dcSAndroid Build Coastguard Worker (v == 0 && seen_digit) ||
228*8fb009dcSAndroid Build Coastguard Worker // Check for overflow.
229*8fb009dcSAndroid Build Coastguard Worker v > UINT64_MAX / 10 || //
230*8fb009dcSAndroid Build Coastguard Worker v * 10 > UINT64_MAX - (c - '0')) {
231*8fb009dcSAndroid Build Coastguard Worker return 0;
232*8fb009dcSAndroid Build Coastguard Worker }
233*8fb009dcSAndroid Build Coastguard Worker v = v * 10 + (c - '0');
234*8fb009dcSAndroid Build Coastguard Worker seen_digit = 1;
235*8fb009dcSAndroid Build Coastguard Worker }
236*8fb009dcSAndroid Build Coastguard Worker
237*8fb009dcSAndroid Build Coastguard Worker *out = v;
238*8fb009dcSAndroid Build Coastguard Worker return seen_digit;
239*8fb009dcSAndroid Build Coastguard Worker }
240*8fb009dcSAndroid Build Coastguard Worker
241*8fb009dcSAndroid Build Coastguard Worker // parse_base128_integer reads a big-endian base-128 integer from |cbs| and sets
242*8fb009dcSAndroid Build Coastguard Worker // |*out| to the result. This is the encoding used in DER for both high tag
243*8fb009dcSAndroid Build Coastguard Worker // number form and OID components.
parse_base128_integer(CBS * cbs,uint64_t * out)244*8fb009dcSAndroid Build Coastguard Worker static int parse_base128_integer(CBS *cbs, uint64_t *out) {
245*8fb009dcSAndroid Build Coastguard Worker uint64_t v = 0;
246*8fb009dcSAndroid Build Coastguard Worker uint8_t b;
247*8fb009dcSAndroid Build Coastguard Worker do {
248*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(cbs, &b)) {
249*8fb009dcSAndroid Build Coastguard Worker return 0;
250*8fb009dcSAndroid Build Coastguard Worker }
251*8fb009dcSAndroid Build Coastguard Worker if ((v >> (64 - 7)) != 0) {
252*8fb009dcSAndroid Build Coastguard Worker // The value is too large.
253*8fb009dcSAndroid Build Coastguard Worker return 0;
254*8fb009dcSAndroid Build Coastguard Worker }
255*8fb009dcSAndroid Build Coastguard Worker if (v == 0 && b == 0x80) {
256*8fb009dcSAndroid Build Coastguard Worker // The value must be minimally encoded.
257*8fb009dcSAndroid Build Coastguard Worker return 0;
258*8fb009dcSAndroid Build Coastguard Worker }
259*8fb009dcSAndroid Build Coastguard Worker v = (v << 7) | (b & 0x7f);
260*8fb009dcSAndroid Build Coastguard Worker
261*8fb009dcSAndroid Build Coastguard Worker // Values end at an octet with the high bit cleared.
262*8fb009dcSAndroid Build Coastguard Worker } while (b & 0x80);
263*8fb009dcSAndroid Build Coastguard Worker
264*8fb009dcSAndroid Build Coastguard Worker *out = v;
265*8fb009dcSAndroid Build Coastguard Worker return 1;
266*8fb009dcSAndroid Build Coastguard Worker }
267*8fb009dcSAndroid Build Coastguard Worker
parse_asn1_tag(CBS * cbs,CBS_ASN1_TAG * out)268*8fb009dcSAndroid Build Coastguard Worker static int parse_asn1_tag(CBS *cbs, CBS_ASN1_TAG *out) {
269*8fb009dcSAndroid Build Coastguard Worker uint8_t tag_byte;
270*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(cbs, &tag_byte)) {
271*8fb009dcSAndroid Build Coastguard Worker return 0;
272*8fb009dcSAndroid Build Coastguard Worker }
273*8fb009dcSAndroid Build Coastguard Worker
274*8fb009dcSAndroid Build Coastguard Worker // ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
275*8fb009dcSAndroid Build Coastguard Worker // number no greater than 30.
276*8fb009dcSAndroid Build Coastguard Worker //
277*8fb009dcSAndroid Build Coastguard Worker // If the number portion is 31 (0x1f, the largest value that fits in the
278*8fb009dcSAndroid Build Coastguard Worker // allotted bits), then the tag is more than one byte long and the
279*8fb009dcSAndroid Build Coastguard Worker // continuation bytes contain the tag number.
280*8fb009dcSAndroid Build Coastguard Worker CBS_ASN1_TAG tag = ((CBS_ASN1_TAG)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT;
281*8fb009dcSAndroid Build Coastguard Worker CBS_ASN1_TAG tag_number = tag_byte & 0x1f;
282*8fb009dcSAndroid Build Coastguard Worker if (tag_number == 0x1f) {
283*8fb009dcSAndroid Build Coastguard Worker uint64_t v;
284*8fb009dcSAndroid Build Coastguard Worker if (!parse_base128_integer(cbs, &v) ||
285*8fb009dcSAndroid Build Coastguard Worker // Check the tag number is within our supported bounds.
286*8fb009dcSAndroid Build Coastguard Worker v > CBS_ASN1_TAG_NUMBER_MASK ||
287*8fb009dcSAndroid Build Coastguard Worker // Small tag numbers should have used low tag number form, even in BER.
288*8fb009dcSAndroid Build Coastguard Worker v < 0x1f) {
289*8fb009dcSAndroid Build Coastguard Worker return 0;
290*8fb009dcSAndroid Build Coastguard Worker }
291*8fb009dcSAndroid Build Coastguard Worker tag_number = (CBS_ASN1_TAG)v;
292*8fb009dcSAndroid Build Coastguard Worker }
293*8fb009dcSAndroid Build Coastguard Worker
294*8fb009dcSAndroid Build Coastguard Worker tag |= tag_number;
295*8fb009dcSAndroid Build Coastguard Worker
296*8fb009dcSAndroid Build Coastguard Worker // Tag [UNIVERSAL 0] is reserved for use by the encoding. Reject it here to
297*8fb009dcSAndroid Build Coastguard Worker // avoid some ambiguity around ANY values and BER indefinite-length EOCs. See
298*8fb009dcSAndroid Build Coastguard Worker // https://crbug.com/boringssl/455.
299*8fb009dcSAndroid Build Coastguard Worker if ((tag & ~CBS_ASN1_CONSTRUCTED) == 0) {
300*8fb009dcSAndroid Build Coastguard Worker return 0;
301*8fb009dcSAndroid Build Coastguard Worker }
302*8fb009dcSAndroid Build Coastguard Worker
303*8fb009dcSAndroid Build Coastguard Worker *out = tag;
304*8fb009dcSAndroid Build Coastguard Worker return 1;
305*8fb009dcSAndroid Build Coastguard Worker }
306*8fb009dcSAndroid Build Coastguard Worker
cbs_get_any_asn1_element(CBS * cbs,CBS * out,CBS_ASN1_TAG * out_tag,size_t * out_header_len,int * out_ber_found,int * out_indefinite,int ber_ok)307*8fb009dcSAndroid Build Coastguard Worker static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag,
308*8fb009dcSAndroid Build Coastguard Worker size_t *out_header_len, int *out_ber_found,
309*8fb009dcSAndroid Build Coastguard Worker int *out_indefinite, int ber_ok) {
310*8fb009dcSAndroid Build Coastguard Worker CBS header = *cbs;
311*8fb009dcSAndroid Build Coastguard Worker CBS throwaway;
312*8fb009dcSAndroid Build Coastguard Worker
313*8fb009dcSAndroid Build Coastguard Worker if (out == NULL) {
314*8fb009dcSAndroid Build Coastguard Worker out = &throwaway;
315*8fb009dcSAndroid Build Coastguard Worker }
316*8fb009dcSAndroid Build Coastguard Worker if (ber_ok) {
317*8fb009dcSAndroid Build Coastguard Worker *out_ber_found = 0;
318*8fb009dcSAndroid Build Coastguard Worker *out_indefinite = 0;
319*8fb009dcSAndroid Build Coastguard Worker } else {
320*8fb009dcSAndroid Build Coastguard Worker assert(out_ber_found == NULL);
321*8fb009dcSAndroid Build Coastguard Worker assert(out_indefinite == NULL);
322*8fb009dcSAndroid Build Coastguard Worker }
323*8fb009dcSAndroid Build Coastguard Worker
324*8fb009dcSAndroid Build Coastguard Worker CBS_ASN1_TAG tag;
325*8fb009dcSAndroid Build Coastguard Worker if (!parse_asn1_tag(&header, &tag)) {
326*8fb009dcSAndroid Build Coastguard Worker return 0;
327*8fb009dcSAndroid Build Coastguard Worker }
328*8fb009dcSAndroid Build Coastguard Worker if (out_tag != NULL) {
329*8fb009dcSAndroid Build Coastguard Worker *out_tag = tag;
330*8fb009dcSAndroid Build Coastguard Worker }
331*8fb009dcSAndroid Build Coastguard Worker
332*8fb009dcSAndroid Build Coastguard Worker uint8_t length_byte;
333*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(&header, &length_byte)) {
334*8fb009dcSAndroid Build Coastguard Worker return 0;
335*8fb009dcSAndroid Build Coastguard Worker }
336*8fb009dcSAndroid Build Coastguard Worker
337*8fb009dcSAndroid Build Coastguard Worker size_t header_len = CBS_len(cbs) - CBS_len(&header);
338*8fb009dcSAndroid Build Coastguard Worker
339*8fb009dcSAndroid Build Coastguard Worker size_t len;
340*8fb009dcSAndroid Build Coastguard Worker // The format for the length encoding is specified in ITU-T X.690 section
341*8fb009dcSAndroid Build Coastguard Worker // 8.1.3.
342*8fb009dcSAndroid Build Coastguard Worker if ((length_byte & 0x80) == 0) {
343*8fb009dcSAndroid Build Coastguard Worker // Short form length.
344*8fb009dcSAndroid Build Coastguard Worker len = ((size_t) length_byte) + header_len;
345*8fb009dcSAndroid Build Coastguard Worker if (out_header_len != NULL) {
346*8fb009dcSAndroid Build Coastguard Worker *out_header_len = header_len;
347*8fb009dcSAndroid Build Coastguard Worker }
348*8fb009dcSAndroid Build Coastguard Worker } else {
349*8fb009dcSAndroid Build Coastguard Worker // The high bit indicate that this is the long form, while the next 7 bits
350*8fb009dcSAndroid Build Coastguard Worker // encode the number of subsequent octets used to encode the length (ITU-T
351*8fb009dcSAndroid Build Coastguard Worker // X.690 clause 8.1.3.5.b).
352*8fb009dcSAndroid Build Coastguard Worker const size_t num_bytes = length_byte & 0x7f;
353*8fb009dcSAndroid Build Coastguard Worker uint64_t len64;
354*8fb009dcSAndroid Build Coastguard Worker
355*8fb009dcSAndroid Build Coastguard Worker if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
356*8fb009dcSAndroid Build Coastguard Worker // indefinite length
357*8fb009dcSAndroid Build Coastguard Worker if (out_header_len != NULL) {
358*8fb009dcSAndroid Build Coastguard Worker *out_header_len = header_len;
359*8fb009dcSAndroid Build Coastguard Worker }
360*8fb009dcSAndroid Build Coastguard Worker *out_ber_found = 1;
361*8fb009dcSAndroid Build Coastguard Worker *out_indefinite = 1;
362*8fb009dcSAndroid Build Coastguard Worker return CBS_get_bytes(cbs, out, header_len);
363*8fb009dcSAndroid Build Coastguard Worker }
364*8fb009dcSAndroid Build Coastguard Worker
365*8fb009dcSAndroid Build Coastguard Worker // ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
366*8fb009dcSAndroid Build Coastguard Worker // used as the first byte of the length. If this parser encounters that
367*8fb009dcSAndroid Build Coastguard Worker // value, num_bytes will be parsed as 127, which will fail this check.
368*8fb009dcSAndroid Build Coastguard Worker if (num_bytes == 0 || num_bytes > 4) {
369*8fb009dcSAndroid Build Coastguard Worker return 0;
370*8fb009dcSAndroid Build Coastguard Worker }
371*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_u(&header, &len64, num_bytes)) {
372*8fb009dcSAndroid Build Coastguard Worker return 0;
373*8fb009dcSAndroid Build Coastguard Worker }
374*8fb009dcSAndroid Build Coastguard Worker // ITU-T X.690 section 10.1 (DER length forms) requires encoding the
375*8fb009dcSAndroid Build Coastguard Worker // length with the minimum number of octets. BER could, technically, have
376*8fb009dcSAndroid Build Coastguard Worker // 125 superfluous zero bytes. We do not attempt to handle that and still
377*8fb009dcSAndroid Build Coastguard Worker // require that the length fit in a |uint32_t| for BER.
378*8fb009dcSAndroid Build Coastguard Worker if (len64 < 128) {
379*8fb009dcSAndroid Build Coastguard Worker // Length should have used short-form encoding.
380*8fb009dcSAndroid Build Coastguard Worker if (ber_ok) {
381*8fb009dcSAndroid Build Coastguard Worker *out_ber_found = 1;
382*8fb009dcSAndroid Build Coastguard Worker } else {
383*8fb009dcSAndroid Build Coastguard Worker return 0;
384*8fb009dcSAndroid Build Coastguard Worker }
385*8fb009dcSAndroid Build Coastguard Worker }
386*8fb009dcSAndroid Build Coastguard Worker if ((len64 >> ((num_bytes - 1) * 8)) == 0) {
387*8fb009dcSAndroid Build Coastguard Worker // Length should have been at least one byte shorter.
388*8fb009dcSAndroid Build Coastguard Worker if (ber_ok) {
389*8fb009dcSAndroid Build Coastguard Worker *out_ber_found = 1;
390*8fb009dcSAndroid Build Coastguard Worker } else {
391*8fb009dcSAndroid Build Coastguard Worker return 0;
392*8fb009dcSAndroid Build Coastguard Worker }
393*8fb009dcSAndroid Build Coastguard Worker }
394*8fb009dcSAndroid Build Coastguard Worker len = len64;
395*8fb009dcSAndroid Build Coastguard Worker if (len + header_len + num_bytes < len) {
396*8fb009dcSAndroid Build Coastguard Worker // Overflow.
397*8fb009dcSAndroid Build Coastguard Worker return 0;
398*8fb009dcSAndroid Build Coastguard Worker }
399*8fb009dcSAndroid Build Coastguard Worker len += header_len + num_bytes;
400*8fb009dcSAndroid Build Coastguard Worker if (out_header_len != NULL) {
401*8fb009dcSAndroid Build Coastguard Worker *out_header_len = header_len + num_bytes;
402*8fb009dcSAndroid Build Coastguard Worker }
403*8fb009dcSAndroid Build Coastguard Worker }
404*8fb009dcSAndroid Build Coastguard Worker
405*8fb009dcSAndroid Build Coastguard Worker return CBS_get_bytes(cbs, out, len);
406*8fb009dcSAndroid Build Coastguard Worker }
407*8fb009dcSAndroid Build Coastguard Worker
CBS_get_any_asn1(CBS * cbs,CBS * out,CBS_ASN1_TAG * out_tag)408*8fb009dcSAndroid Build Coastguard Worker int CBS_get_any_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag) {
409*8fb009dcSAndroid Build Coastguard Worker size_t header_len;
410*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) {
411*8fb009dcSAndroid Build Coastguard Worker return 0;
412*8fb009dcSAndroid Build Coastguard Worker }
413*8fb009dcSAndroid Build Coastguard Worker
414*8fb009dcSAndroid Build Coastguard Worker if (!CBS_skip(out, header_len)) {
415*8fb009dcSAndroid Build Coastguard Worker assert(0);
416*8fb009dcSAndroid Build Coastguard Worker return 0;
417*8fb009dcSAndroid Build Coastguard Worker }
418*8fb009dcSAndroid Build Coastguard Worker
419*8fb009dcSAndroid Build Coastguard Worker return 1;
420*8fb009dcSAndroid Build Coastguard Worker }
421*8fb009dcSAndroid Build Coastguard Worker
CBS_get_any_asn1_element(CBS * cbs,CBS * out,CBS_ASN1_TAG * out_tag,size_t * out_header_len)422*8fb009dcSAndroid Build Coastguard Worker int CBS_get_any_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag,
423*8fb009dcSAndroid Build Coastguard Worker size_t *out_header_len) {
424*8fb009dcSAndroid Build Coastguard Worker return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, NULL, NULL,
425*8fb009dcSAndroid Build Coastguard Worker /*ber_ok=*/0);
426*8fb009dcSAndroid Build Coastguard Worker }
427*8fb009dcSAndroid Build Coastguard Worker
CBS_get_any_ber_asn1_element(CBS * cbs,CBS * out,CBS_ASN1_TAG * out_tag,size_t * out_header_len,int * out_ber_found,int * out_indefinite)428*8fb009dcSAndroid Build Coastguard Worker int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag,
429*8fb009dcSAndroid Build Coastguard Worker size_t *out_header_len, int *out_ber_found,
430*8fb009dcSAndroid Build Coastguard Worker int *out_indefinite) {
431*8fb009dcSAndroid Build Coastguard Worker int ber_found_temp;
432*8fb009dcSAndroid Build Coastguard Worker return cbs_get_any_asn1_element(
433*8fb009dcSAndroid Build Coastguard Worker cbs, out, out_tag, out_header_len,
434*8fb009dcSAndroid Build Coastguard Worker out_ber_found ? out_ber_found : &ber_found_temp, out_indefinite,
435*8fb009dcSAndroid Build Coastguard Worker /*ber_ok=*/1);
436*8fb009dcSAndroid Build Coastguard Worker }
437*8fb009dcSAndroid Build Coastguard Worker
cbs_get_asn1(CBS * cbs,CBS * out,CBS_ASN1_TAG tag_value,int skip_header)438*8fb009dcSAndroid Build Coastguard Worker static int cbs_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value,
439*8fb009dcSAndroid Build Coastguard Worker int skip_header) {
440*8fb009dcSAndroid Build Coastguard Worker size_t header_len;
441*8fb009dcSAndroid Build Coastguard Worker CBS_ASN1_TAG tag;
442*8fb009dcSAndroid Build Coastguard Worker CBS throwaway;
443*8fb009dcSAndroid Build Coastguard Worker
444*8fb009dcSAndroid Build Coastguard Worker if (out == NULL) {
445*8fb009dcSAndroid Build Coastguard Worker out = &throwaway;
446*8fb009dcSAndroid Build Coastguard Worker }
447*8fb009dcSAndroid Build Coastguard Worker
448*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
449*8fb009dcSAndroid Build Coastguard Worker tag != tag_value) {
450*8fb009dcSAndroid Build Coastguard Worker return 0;
451*8fb009dcSAndroid Build Coastguard Worker }
452*8fb009dcSAndroid Build Coastguard Worker
453*8fb009dcSAndroid Build Coastguard Worker if (skip_header && !CBS_skip(out, header_len)) {
454*8fb009dcSAndroid Build Coastguard Worker assert(0);
455*8fb009dcSAndroid Build Coastguard Worker return 0;
456*8fb009dcSAndroid Build Coastguard Worker }
457*8fb009dcSAndroid Build Coastguard Worker
458*8fb009dcSAndroid Build Coastguard Worker return 1;
459*8fb009dcSAndroid Build Coastguard Worker }
460*8fb009dcSAndroid Build Coastguard Worker
CBS_get_asn1(CBS * cbs,CBS * out,CBS_ASN1_TAG tag_value)461*8fb009dcSAndroid Build Coastguard Worker int CBS_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value) {
462*8fb009dcSAndroid Build Coastguard Worker return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
463*8fb009dcSAndroid Build Coastguard Worker }
464*8fb009dcSAndroid Build Coastguard Worker
CBS_get_asn1_element(CBS * cbs,CBS * out,CBS_ASN1_TAG tag_value)465*8fb009dcSAndroid Build Coastguard Worker int CBS_get_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value) {
466*8fb009dcSAndroid Build Coastguard Worker return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
467*8fb009dcSAndroid Build Coastguard Worker }
468*8fb009dcSAndroid Build Coastguard Worker
CBS_peek_asn1_tag(const CBS * cbs,CBS_ASN1_TAG tag_value)469*8fb009dcSAndroid Build Coastguard Worker int CBS_peek_asn1_tag(const CBS *cbs, CBS_ASN1_TAG tag_value) {
470*8fb009dcSAndroid Build Coastguard Worker CBS copy = *cbs;
471*8fb009dcSAndroid Build Coastguard Worker CBS_ASN1_TAG actual_tag;
472*8fb009dcSAndroid Build Coastguard Worker return parse_asn1_tag(©, &actual_tag) && tag_value == actual_tag;
473*8fb009dcSAndroid Build Coastguard Worker }
474*8fb009dcSAndroid Build Coastguard Worker
CBS_get_asn1_uint64(CBS * cbs,uint64_t * out)475*8fb009dcSAndroid Build Coastguard Worker int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
476*8fb009dcSAndroid Build Coastguard Worker CBS bytes;
477*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER) ||
478*8fb009dcSAndroid Build Coastguard Worker !CBS_is_unsigned_asn1_integer(&bytes)) {
479*8fb009dcSAndroid Build Coastguard Worker return 0;
480*8fb009dcSAndroid Build Coastguard Worker }
481*8fb009dcSAndroid Build Coastguard Worker
482*8fb009dcSAndroid Build Coastguard Worker *out = 0;
483*8fb009dcSAndroid Build Coastguard Worker const uint8_t *data = CBS_data(&bytes);
484*8fb009dcSAndroid Build Coastguard Worker size_t len = CBS_len(&bytes);
485*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < len; i++) {
486*8fb009dcSAndroid Build Coastguard Worker if ((*out >> 56) != 0) {
487*8fb009dcSAndroid Build Coastguard Worker // Too large to represent as a uint64_t.
488*8fb009dcSAndroid Build Coastguard Worker return 0;
489*8fb009dcSAndroid Build Coastguard Worker }
490*8fb009dcSAndroid Build Coastguard Worker *out <<= 8;
491*8fb009dcSAndroid Build Coastguard Worker *out |= data[i];
492*8fb009dcSAndroid Build Coastguard Worker }
493*8fb009dcSAndroid Build Coastguard Worker
494*8fb009dcSAndroid Build Coastguard Worker return 1;
495*8fb009dcSAndroid Build Coastguard Worker }
496*8fb009dcSAndroid Build Coastguard Worker
CBS_get_asn1_int64(CBS * cbs,int64_t * out)497*8fb009dcSAndroid Build Coastguard Worker int CBS_get_asn1_int64(CBS *cbs, int64_t *out) {
498*8fb009dcSAndroid Build Coastguard Worker int is_negative;
499*8fb009dcSAndroid Build Coastguard Worker CBS bytes;
500*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER) ||
501*8fb009dcSAndroid Build Coastguard Worker !CBS_is_valid_asn1_integer(&bytes, &is_negative)) {
502*8fb009dcSAndroid Build Coastguard Worker return 0;
503*8fb009dcSAndroid Build Coastguard Worker }
504*8fb009dcSAndroid Build Coastguard Worker const uint8_t *data = CBS_data(&bytes);
505*8fb009dcSAndroid Build Coastguard Worker const size_t len = CBS_len(&bytes);
506*8fb009dcSAndroid Build Coastguard Worker if (len > sizeof(int64_t)) {
507*8fb009dcSAndroid Build Coastguard Worker return 0;
508*8fb009dcSAndroid Build Coastguard Worker }
509*8fb009dcSAndroid Build Coastguard Worker uint8_t sign_extend[sizeof(int64_t)];
510*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(sign_extend, is_negative ? 0xff : 0, sizeof(sign_extend));
511*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(sign_extend + sizeof(int64_t) - len, data, len);
512*8fb009dcSAndroid Build Coastguard Worker *out = CRYPTO_load_u64_be(sign_extend);
513*8fb009dcSAndroid Build Coastguard Worker return 1;
514*8fb009dcSAndroid Build Coastguard Worker }
515*8fb009dcSAndroid Build Coastguard Worker
CBS_get_asn1_bool(CBS * cbs,int * out)516*8fb009dcSAndroid Build Coastguard Worker int CBS_get_asn1_bool(CBS *cbs, int *out) {
517*8fb009dcSAndroid Build Coastguard Worker CBS bytes;
518*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) ||
519*8fb009dcSAndroid Build Coastguard Worker CBS_len(&bytes) != 1) {
520*8fb009dcSAndroid Build Coastguard Worker return 0;
521*8fb009dcSAndroid Build Coastguard Worker }
522*8fb009dcSAndroid Build Coastguard Worker
523*8fb009dcSAndroid Build Coastguard Worker const uint8_t value = *CBS_data(&bytes);
524*8fb009dcSAndroid Build Coastguard Worker if (value != 0 && value != 0xff) {
525*8fb009dcSAndroid Build Coastguard Worker return 0;
526*8fb009dcSAndroid Build Coastguard Worker }
527*8fb009dcSAndroid Build Coastguard Worker
528*8fb009dcSAndroid Build Coastguard Worker *out = !!value;
529*8fb009dcSAndroid Build Coastguard Worker return 1;
530*8fb009dcSAndroid Build Coastguard Worker }
531*8fb009dcSAndroid Build Coastguard Worker
CBS_get_optional_asn1(CBS * cbs,CBS * out,int * out_present,CBS_ASN1_TAG tag)532*8fb009dcSAndroid Build Coastguard Worker int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, CBS_ASN1_TAG tag) {
533*8fb009dcSAndroid Build Coastguard Worker int present = 0;
534*8fb009dcSAndroid Build Coastguard Worker
535*8fb009dcSAndroid Build Coastguard Worker if (CBS_peek_asn1_tag(cbs, tag)) {
536*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_asn1(cbs, out, tag)) {
537*8fb009dcSAndroid Build Coastguard Worker return 0;
538*8fb009dcSAndroid Build Coastguard Worker }
539*8fb009dcSAndroid Build Coastguard Worker present = 1;
540*8fb009dcSAndroid Build Coastguard Worker }
541*8fb009dcSAndroid Build Coastguard Worker
542*8fb009dcSAndroid Build Coastguard Worker if (out_present != NULL) {
543*8fb009dcSAndroid Build Coastguard Worker *out_present = present;
544*8fb009dcSAndroid Build Coastguard Worker }
545*8fb009dcSAndroid Build Coastguard Worker
546*8fb009dcSAndroid Build Coastguard Worker return 1;
547*8fb009dcSAndroid Build Coastguard Worker }
548*8fb009dcSAndroid Build Coastguard Worker
CBS_get_optional_asn1_octet_string(CBS * cbs,CBS * out,int * out_present,CBS_ASN1_TAG tag)549*8fb009dcSAndroid Build Coastguard Worker int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
550*8fb009dcSAndroid Build Coastguard Worker CBS_ASN1_TAG tag) {
551*8fb009dcSAndroid Build Coastguard Worker CBS child;
552*8fb009dcSAndroid Build Coastguard Worker int present;
553*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
554*8fb009dcSAndroid Build Coastguard Worker return 0;
555*8fb009dcSAndroid Build Coastguard Worker }
556*8fb009dcSAndroid Build Coastguard Worker if (present) {
557*8fb009dcSAndroid Build Coastguard Worker assert(out);
558*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
559*8fb009dcSAndroid Build Coastguard Worker CBS_len(&child) != 0) {
560*8fb009dcSAndroid Build Coastguard Worker return 0;
561*8fb009dcSAndroid Build Coastguard Worker }
562*8fb009dcSAndroid Build Coastguard Worker } else {
563*8fb009dcSAndroid Build Coastguard Worker CBS_init(out, NULL, 0);
564*8fb009dcSAndroid Build Coastguard Worker }
565*8fb009dcSAndroid Build Coastguard Worker if (out_present) {
566*8fb009dcSAndroid Build Coastguard Worker *out_present = present;
567*8fb009dcSAndroid Build Coastguard Worker }
568*8fb009dcSAndroid Build Coastguard Worker return 1;
569*8fb009dcSAndroid Build Coastguard Worker }
570*8fb009dcSAndroid Build Coastguard Worker
CBS_get_optional_asn1_uint64(CBS * cbs,uint64_t * out,CBS_ASN1_TAG tag,uint64_t default_value)571*8fb009dcSAndroid Build Coastguard Worker int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, CBS_ASN1_TAG tag,
572*8fb009dcSAndroid Build Coastguard Worker uint64_t default_value) {
573*8fb009dcSAndroid Build Coastguard Worker CBS child;
574*8fb009dcSAndroid Build Coastguard Worker int present;
575*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
576*8fb009dcSAndroid Build Coastguard Worker return 0;
577*8fb009dcSAndroid Build Coastguard Worker }
578*8fb009dcSAndroid Build Coastguard Worker if (present) {
579*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_asn1_uint64(&child, out) ||
580*8fb009dcSAndroid Build Coastguard Worker CBS_len(&child) != 0) {
581*8fb009dcSAndroid Build Coastguard Worker return 0;
582*8fb009dcSAndroid Build Coastguard Worker }
583*8fb009dcSAndroid Build Coastguard Worker } else {
584*8fb009dcSAndroid Build Coastguard Worker *out = default_value;
585*8fb009dcSAndroid Build Coastguard Worker }
586*8fb009dcSAndroid Build Coastguard Worker return 1;
587*8fb009dcSAndroid Build Coastguard Worker }
588*8fb009dcSAndroid Build Coastguard Worker
CBS_get_optional_asn1_bool(CBS * cbs,int * out,CBS_ASN1_TAG tag,int default_value)589*8fb009dcSAndroid Build Coastguard Worker int CBS_get_optional_asn1_bool(CBS *cbs, int *out, CBS_ASN1_TAG tag,
590*8fb009dcSAndroid Build Coastguard Worker int default_value) {
591*8fb009dcSAndroid Build Coastguard Worker CBS child, child2;
592*8fb009dcSAndroid Build Coastguard Worker int present;
593*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
594*8fb009dcSAndroid Build Coastguard Worker return 0;
595*8fb009dcSAndroid Build Coastguard Worker }
596*8fb009dcSAndroid Build Coastguard Worker if (present) {
597*8fb009dcSAndroid Build Coastguard Worker uint8_t boolean;
598*8fb009dcSAndroid Build Coastguard Worker
599*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
600*8fb009dcSAndroid Build Coastguard Worker CBS_len(&child2) != 1 ||
601*8fb009dcSAndroid Build Coastguard Worker CBS_len(&child) != 0) {
602*8fb009dcSAndroid Build Coastguard Worker return 0;
603*8fb009dcSAndroid Build Coastguard Worker }
604*8fb009dcSAndroid Build Coastguard Worker
605*8fb009dcSAndroid Build Coastguard Worker boolean = CBS_data(&child2)[0];
606*8fb009dcSAndroid Build Coastguard Worker if (boolean == 0) {
607*8fb009dcSAndroid Build Coastguard Worker *out = 0;
608*8fb009dcSAndroid Build Coastguard Worker } else if (boolean == 0xff) {
609*8fb009dcSAndroid Build Coastguard Worker *out = 1;
610*8fb009dcSAndroid Build Coastguard Worker } else {
611*8fb009dcSAndroid Build Coastguard Worker return 0;
612*8fb009dcSAndroid Build Coastguard Worker }
613*8fb009dcSAndroid Build Coastguard Worker } else {
614*8fb009dcSAndroid Build Coastguard Worker *out = default_value;
615*8fb009dcSAndroid Build Coastguard Worker }
616*8fb009dcSAndroid Build Coastguard Worker return 1;
617*8fb009dcSAndroid Build Coastguard Worker }
618*8fb009dcSAndroid Build Coastguard Worker
CBS_is_valid_asn1_bitstring(const CBS * cbs)619*8fb009dcSAndroid Build Coastguard Worker int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
620*8fb009dcSAndroid Build Coastguard Worker CBS in = *cbs;
621*8fb009dcSAndroid Build Coastguard Worker uint8_t num_unused_bits;
622*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(&in, &num_unused_bits) ||
623*8fb009dcSAndroid Build Coastguard Worker num_unused_bits > 7) {
624*8fb009dcSAndroid Build Coastguard Worker return 0;
625*8fb009dcSAndroid Build Coastguard Worker }
626*8fb009dcSAndroid Build Coastguard Worker
627*8fb009dcSAndroid Build Coastguard Worker if (num_unused_bits == 0) {
628*8fb009dcSAndroid Build Coastguard Worker return 1;
629*8fb009dcSAndroid Build Coastguard Worker }
630*8fb009dcSAndroid Build Coastguard Worker
631*8fb009dcSAndroid Build Coastguard Worker // All num_unused_bits bits must exist and be zeros.
632*8fb009dcSAndroid Build Coastguard Worker uint8_t last;
633*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_last_u8(&in, &last) ||
634*8fb009dcSAndroid Build Coastguard Worker (last & ((1 << num_unused_bits) - 1)) != 0) {
635*8fb009dcSAndroid Build Coastguard Worker return 0;
636*8fb009dcSAndroid Build Coastguard Worker }
637*8fb009dcSAndroid Build Coastguard Worker
638*8fb009dcSAndroid Build Coastguard Worker return 1;
639*8fb009dcSAndroid Build Coastguard Worker }
640*8fb009dcSAndroid Build Coastguard Worker
CBS_asn1_bitstring_has_bit(const CBS * cbs,unsigned bit)641*8fb009dcSAndroid Build Coastguard Worker int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
642*8fb009dcSAndroid Build Coastguard Worker if (!CBS_is_valid_asn1_bitstring(cbs)) {
643*8fb009dcSAndroid Build Coastguard Worker return 0;
644*8fb009dcSAndroid Build Coastguard Worker }
645*8fb009dcSAndroid Build Coastguard Worker
646*8fb009dcSAndroid Build Coastguard Worker const unsigned byte_num = (bit >> 3) + 1;
647*8fb009dcSAndroid Build Coastguard Worker const unsigned bit_num = 7 - (bit & 7);
648*8fb009dcSAndroid Build Coastguard Worker
649*8fb009dcSAndroid Build Coastguard Worker // Unused bits are zero, and this function does not distinguish between
650*8fb009dcSAndroid Build Coastguard Worker // missing and unset bits. Thus it is sufficient to do a byte-level length
651*8fb009dcSAndroid Build Coastguard Worker // check.
652*8fb009dcSAndroid Build Coastguard Worker return byte_num < CBS_len(cbs) &&
653*8fb009dcSAndroid Build Coastguard Worker (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
654*8fb009dcSAndroid Build Coastguard Worker }
655*8fb009dcSAndroid Build Coastguard Worker
CBS_is_valid_asn1_integer(const CBS * cbs,int * out_is_negative)656*8fb009dcSAndroid Build Coastguard Worker int CBS_is_valid_asn1_integer(const CBS *cbs, int *out_is_negative) {
657*8fb009dcSAndroid Build Coastguard Worker CBS copy = *cbs;
658*8fb009dcSAndroid Build Coastguard Worker uint8_t first_byte, second_byte;
659*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(©, &first_byte)) {
660*8fb009dcSAndroid Build Coastguard Worker return 0; // INTEGERs may not be empty.
661*8fb009dcSAndroid Build Coastguard Worker }
662*8fb009dcSAndroid Build Coastguard Worker if (out_is_negative != NULL) {
663*8fb009dcSAndroid Build Coastguard Worker *out_is_negative = (first_byte & 0x80) != 0;
664*8fb009dcSAndroid Build Coastguard Worker }
665*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(©, &second_byte)) {
666*8fb009dcSAndroid Build Coastguard Worker return 1; // One byte INTEGERs are always minimal.
667*8fb009dcSAndroid Build Coastguard Worker }
668*8fb009dcSAndroid Build Coastguard Worker if ((first_byte == 0x00 && (second_byte & 0x80) == 0) ||
669*8fb009dcSAndroid Build Coastguard Worker (first_byte == 0xff && (second_byte & 0x80) != 0)) {
670*8fb009dcSAndroid Build Coastguard Worker return 0; // The value is minimal iff the first 9 bits are not all equal.
671*8fb009dcSAndroid Build Coastguard Worker }
672*8fb009dcSAndroid Build Coastguard Worker return 1;
673*8fb009dcSAndroid Build Coastguard Worker }
674*8fb009dcSAndroid Build Coastguard Worker
CBS_is_unsigned_asn1_integer(const CBS * cbs)675*8fb009dcSAndroid Build Coastguard Worker int CBS_is_unsigned_asn1_integer(const CBS *cbs) {
676*8fb009dcSAndroid Build Coastguard Worker int is_negative;
677*8fb009dcSAndroid Build Coastguard Worker return CBS_is_valid_asn1_integer(cbs, &is_negative) && !is_negative;
678*8fb009dcSAndroid Build Coastguard Worker }
679*8fb009dcSAndroid Build Coastguard Worker
add_decimal(CBB * out,uint64_t v)680*8fb009dcSAndroid Build Coastguard Worker static int add_decimal(CBB *out, uint64_t v) {
681*8fb009dcSAndroid Build Coastguard Worker char buf[DECIMAL_SIZE(uint64_t) + 1];
682*8fb009dcSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "%" PRIu64, v);
683*8fb009dcSAndroid Build Coastguard Worker return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf));
684*8fb009dcSAndroid Build Coastguard Worker }
685*8fb009dcSAndroid Build Coastguard Worker
CBS_is_valid_asn1_oid(const CBS * cbs)686*8fb009dcSAndroid Build Coastguard Worker int CBS_is_valid_asn1_oid(const CBS *cbs) {
687*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(cbs) == 0) {
688*8fb009dcSAndroid Build Coastguard Worker return 0; // OID encodings cannot be empty.
689*8fb009dcSAndroid Build Coastguard Worker }
690*8fb009dcSAndroid Build Coastguard Worker
691*8fb009dcSAndroid Build Coastguard Worker CBS copy = *cbs;
692*8fb009dcSAndroid Build Coastguard Worker uint8_t v, prev = 0;
693*8fb009dcSAndroid Build Coastguard Worker while (CBS_get_u8(©, &v)) {
694*8fb009dcSAndroid Build Coastguard Worker // OID encodings are a sequence of minimally-encoded base-128 integers (see
695*8fb009dcSAndroid Build Coastguard Worker // |parse_base128_integer|). If |prev|'s MSB was clear, it was the last byte
696*8fb009dcSAndroid Build Coastguard Worker // of an integer (or |v| is the first byte). |v| is then the first byte of
697*8fb009dcSAndroid Build Coastguard Worker // the next integer. If first byte of an integer is 0x80, it is not
698*8fb009dcSAndroid Build Coastguard Worker // minimally-encoded.
699*8fb009dcSAndroid Build Coastguard Worker if ((prev & 0x80) == 0 && v == 0x80) {
700*8fb009dcSAndroid Build Coastguard Worker return 0;
701*8fb009dcSAndroid Build Coastguard Worker }
702*8fb009dcSAndroid Build Coastguard Worker prev = v;
703*8fb009dcSAndroid Build Coastguard Worker }
704*8fb009dcSAndroid Build Coastguard Worker
705*8fb009dcSAndroid Build Coastguard Worker // The last byte should must end an integer encoding.
706*8fb009dcSAndroid Build Coastguard Worker return (prev & 0x80) == 0;
707*8fb009dcSAndroid Build Coastguard Worker }
708*8fb009dcSAndroid Build Coastguard Worker
CBS_asn1_oid_to_text(const CBS * cbs)709*8fb009dcSAndroid Build Coastguard Worker char *CBS_asn1_oid_to_text(const CBS *cbs) {
710*8fb009dcSAndroid Build Coastguard Worker CBB cbb;
711*8fb009dcSAndroid Build Coastguard Worker if (!CBB_init(&cbb, 32)) {
712*8fb009dcSAndroid Build Coastguard Worker goto err;
713*8fb009dcSAndroid Build Coastguard Worker }
714*8fb009dcSAndroid Build Coastguard Worker
715*8fb009dcSAndroid Build Coastguard Worker CBS copy = *cbs;
716*8fb009dcSAndroid Build Coastguard Worker // The first component is 40 * value1 + value2, where value1 is 0, 1, or 2.
717*8fb009dcSAndroid Build Coastguard Worker uint64_t v;
718*8fb009dcSAndroid Build Coastguard Worker if (!parse_base128_integer(©, &v)) {
719*8fb009dcSAndroid Build Coastguard Worker goto err;
720*8fb009dcSAndroid Build Coastguard Worker }
721*8fb009dcSAndroid Build Coastguard Worker
722*8fb009dcSAndroid Build Coastguard Worker if (v >= 80) {
723*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) ||
724*8fb009dcSAndroid Build Coastguard Worker !add_decimal(&cbb, v - 80)) {
725*8fb009dcSAndroid Build Coastguard Worker goto err;
726*8fb009dcSAndroid Build Coastguard Worker }
727*8fb009dcSAndroid Build Coastguard Worker } else if (!add_decimal(&cbb, v / 40) ||
728*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&cbb, '.') ||
729*8fb009dcSAndroid Build Coastguard Worker !add_decimal(&cbb, v % 40)) {
730*8fb009dcSAndroid Build Coastguard Worker goto err;
731*8fb009dcSAndroid Build Coastguard Worker }
732*8fb009dcSAndroid Build Coastguard Worker
733*8fb009dcSAndroid Build Coastguard Worker while (CBS_len(©) != 0) {
734*8fb009dcSAndroid Build Coastguard Worker if (!parse_base128_integer(©, &v) ||
735*8fb009dcSAndroid Build Coastguard Worker !CBB_add_u8(&cbb, '.') ||
736*8fb009dcSAndroid Build Coastguard Worker !add_decimal(&cbb, v)) {
737*8fb009dcSAndroid Build Coastguard Worker goto err;
738*8fb009dcSAndroid Build Coastguard Worker }
739*8fb009dcSAndroid Build Coastguard Worker }
740*8fb009dcSAndroid Build Coastguard Worker
741*8fb009dcSAndroid Build Coastguard Worker uint8_t *txt;
742*8fb009dcSAndroid Build Coastguard Worker size_t txt_len;
743*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_u8(&cbb, '\0') ||
744*8fb009dcSAndroid Build Coastguard Worker !CBB_finish(&cbb, &txt, &txt_len)) {
745*8fb009dcSAndroid Build Coastguard Worker goto err;
746*8fb009dcSAndroid Build Coastguard Worker }
747*8fb009dcSAndroid Build Coastguard Worker
748*8fb009dcSAndroid Build Coastguard Worker return (char *)txt;
749*8fb009dcSAndroid Build Coastguard Worker
750*8fb009dcSAndroid Build Coastguard Worker err:
751*8fb009dcSAndroid Build Coastguard Worker CBB_cleanup(&cbb);
752*8fb009dcSAndroid Build Coastguard Worker return NULL;
753*8fb009dcSAndroid Build Coastguard Worker }
754*8fb009dcSAndroid Build Coastguard Worker
cbs_get_two_digits(CBS * cbs,int * out)755*8fb009dcSAndroid Build Coastguard Worker static int cbs_get_two_digits(CBS *cbs, int *out) {
756*8fb009dcSAndroid Build Coastguard Worker uint8_t first_digit, second_digit;
757*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(cbs, &first_digit)) {
758*8fb009dcSAndroid Build Coastguard Worker return 0;
759*8fb009dcSAndroid Build Coastguard Worker }
760*8fb009dcSAndroid Build Coastguard Worker if (!OPENSSL_isdigit(first_digit)) {
761*8fb009dcSAndroid Build Coastguard Worker return 0;
762*8fb009dcSAndroid Build Coastguard Worker }
763*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_u8(cbs, &second_digit)) {
764*8fb009dcSAndroid Build Coastguard Worker return 0;
765*8fb009dcSAndroid Build Coastguard Worker }
766*8fb009dcSAndroid Build Coastguard Worker if (!OPENSSL_isdigit(second_digit)) {
767*8fb009dcSAndroid Build Coastguard Worker return 0;
768*8fb009dcSAndroid Build Coastguard Worker }
769*8fb009dcSAndroid Build Coastguard Worker *out = (first_digit - '0') * 10 + (second_digit - '0');
770*8fb009dcSAndroid Build Coastguard Worker return 1;
771*8fb009dcSAndroid Build Coastguard Worker }
772*8fb009dcSAndroid Build Coastguard Worker
is_valid_day(int year,int month,int day)773*8fb009dcSAndroid Build Coastguard Worker static int is_valid_day(int year, int month, int day) {
774*8fb009dcSAndroid Build Coastguard Worker if (day < 1) {
775*8fb009dcSAndroid Build Coastguard Worker return 0;
776*8fb009dcSAndroid Build Coastguard Worker }
777*8fb009dcSAndroid Build Coastguard Worker switch (month) {
778*8fb009dcSAndroid Build Coastguard Worker case 1:
779*8fb009dcSAndroid Build Coastguard Worker case 3:
780*8fb009dcSAndroid Build Coastguard Worker case 5:
781*8fb009dcSAndroid Build Coastguard Worker case 7:
782*8fb009dcSAndroid Build Coastguard Worker case 8:
783*8fb009dcSAndroid Build Coastguard Worker case 10:
784*8fb009dcSAndroid Build Coastguard Worker case 12:
785*8fb009dcSAndroid Build Coastguard Worker return day <= 31;
786*8fb009dcSAndroid Build Coastguard Worker case 4:
787*8fb009dcSAndroid Build Coastguard Worker case 6:
788*8fb009dcSAndroid Build Coastguard Worker case 9:
789*8fb009dcSAndroid Build Coastguard Worker case 11:
790*8fb009dcSAndroid Build Coastguard Worker return day <= 30;
791*8fb009dcSAndroid Build Coastguard Worker case 2:
792*8fb009dcSAndroid Build Coastguard Worker if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
793*8fb009dcSAndroid Build Coastguard Worker return day <= 29;
794*8fb009dcSAndroid Build Coastguard Worker } else {
795*8fb009dcSAndroid Build Coastguard Worker return day <= 28;
796*8fb009dcSAndroid Build Coastguard Worker }
797*8fb009dcSAndroid Build Coastguard Worker default:
798*8fb009dcSAndroid Build Coastguard Worker return 0;
799*8fb009dcSAndroid Build Coastguard Worker }
800*8fb009dcSAndroid Build Coastguard Worker }
801*8fb009dcSAndroid Build Coastguard Worker
CBS_parse_rfc5280_time_internal(const CBS * cbs,int is_gentime,int allow_timezone_offset,struct tm * out_tm)802*8fb009dcSAndroid Build Coastguard Worker static int CBS_parse_rfc5280_time_internal(const CBS *cbs, int is_gentime,
803*8fb009dcSAndroid Build Coastguard Worker int allow_timezone_offset,
804*8fb009dcSAndroid Build Coastguard Worker struct tm *out_tm) {
805*8fb009dcSAndroid Build Coastguard Worker int year, month, day, hour, min, sec, tmp;
806*8fb009dcSAndroid Build Coastguard Worker CBS copy = *cbs;
807*8fb009dcSAndroid Build Coastguard Worker uint8_t tz;
808*8fb009dcSAndroid Build Coastguard Worker
809*8fb009dcSAndroid Build Coastguard Worker if (is_gentime) {
810*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_two_digits(©, &tmp)) {
811*8fb009dcSAndroid Build Coastguard Worker return 0;
812*8fb009dcSAndroid Build Coastguard Worker }
813*8fb009dcSAndroid Build Coastguard Worker year = tmp * 100;
814*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_two_digits(©, &tmp)) {
815*8fb009dcSAndroid Build Coastguard Worker return 0;
816*8fb009dcSAndroid Build Coastguard Worker }
817*8fb009dcSAndroid Build Coastguard Worker year += tmp;
818*8fb009dcSAndroid Build Coastguard Worker } else {
819*8fb009dcSAndroid Build Coastguard Worker year = 1900;
820*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_two_digits(©, &tmp)) {
821*8fb009dcSAndroid Build Coastguard Worker return 0;
822*8fb009dcSAndroid Build Coastguard Worker }
823*8fb009dcSAndroid Build Coastguard Worker year += tmp;
824*8fb009dcSAndroid Build Coastguard Worker if (year < 1950) {
825*8fb009dcSAndroid Build Coastguard Worker year += 100;
826*8fb009dcSAndroid Build Coastguard Worker }
827*8fb009dcSAndroid Build Coastguard Worker if (year >= 2050) {
828*8fb009dcSAndroid Build Coastguard Worker return 0; // A Generalized time must be used.
829*8fb009dcSAndroid Build Coastguard Worker }
830*8fb009dcSAndroid Build Coastguard Worker }
831*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_two_digits(©, &month) || month < 1 ||
832*8fb009dcSAndroid Build Coastguard Worker month > 12 || // Reject invalid months.
833*8fb009dcSAndroid Build Coastguard Worker !cbs_get_two_digits(©, &day) ||
834*8fb009dcSAndroid Build Coastguard Worker !is_valid_day(year, month, day) || // Reject invalid days.
835*8fb009dcSAndroid Build Coastguard Worker !cbs_get_two_digits(©, &hour) ||
836*8fb009dcSAndroid Build Coastguard Worker hour > 23 || // Reject invalid hours.
837*8fb009dcSAndroid Build Coastguard Worker !cbs_get_two_digits(©, &min) ||
838*8fb009dcSAndroid Build Coastguard Worker min > 59 || // Reject invalid minutes.
839*8fb009dcSAndroid Build Coastguard Worker !cbs_get_two_digits(©, &sec) || sec > 59 || !CBS_get_u8(©, &tz)) {
840*8fb009dcSAndroid Build Coastguard Worker return 0;
841*8fb009dcSAndroid Build Coastguard Worker }
842*8fb009dcSAndroid Build Coastguard Worker
843*8fb009dcSAndroid Build Coastguard Worker int offset_sign = 0;
844*8fb009dcSAndroid Build Coastguard Worker switch (tz) {
845*8fb009dcSAndroid Build Coastguard Worker case 'Z':
846*8fb009dcSAndroid Build Coastguard Worker break; // We correctly have 'Z' on the end as per spec.
847*8fb009dcSAndroid Build Coastguard Worker case '+':
848*8fb009dcSAndroid Build Coastguard Worker offset_sign = 1;
849*8fb009dcSAndroid Build Coastguard Worker break; // Should not be allowed per RFC 5280.
850*8fb009dcSAndroid Build Coastguard Worker case '-':
851*8fb009dcSAndroid Build Coastguard Worker offset_sign = -1;
852*8fb009dcSAndroid Build Coastguard Worker break; // Should not be allowed per RFC 5280.
853*8fb009dcSAndroid Build Coastguard Worker default:
854*8fb009dcSAndroid Build Coastguard Worker return 0; // Reject anything else after the time.
855*8fb009dcSAndroid Build Coastguard Worker }
856*8fb009dcSAndroid Build Coastguard Worker
857*8fb009dcSAndroid Build Coastguard Worker // If allow_timezone_offset is non-zero, allow for a four digit timezone
858*8fb009dcSAndroid Build Coastguard Worker // offset to be specified even though this is not allowed by RFC 5280. We are
859*8fb009dcSAndroid Build Coastguard Worker // permissive of this for UTCTimes due to the unfortunate existence of
860*8fb009dcSAndroid Build Coastguard Worker // artisinally rolled long lived certificates that were baked into places that
861*8fb009dcSAndroid Build Coastguard Worker // are now difficult to change. These certificates were generated with the
862*8fb009dcSAndroid Build Coastguard Worker // 'openssl' command that permissively allowed the creation of certificates
863*8fb009dcSAndroid Build Coastguard Worker // with notBefore and notAfter times specified as strings for direct
864*8fb009dcSAndroid Build Coastguard Worker // certificate inclusion on the command line. For context see cl/237068815.
865*8fb009dcSAndroid Build Coastguard Worker //
866*8fb009dcSAndroid Build Coastguard Worker // TODO(bbe): This has been expunged from public web-pki as the ecosystem has
867*8fb009dcSAndroid Build Coastguard Worker // managed to encourage CA compliance with standards. We should find a way to
868*8fb009dcSAndroid Build Coastguard Worker // get rid of this or make it off by default.
869*8fb009dcSAndroid Build Coastguard Worker int offset_seconds = 0;
870*8fb009dcSAndroid Build Coastguard Worker if (offset_sign != 0) {
871*8fb009dcSAndroid Build Coastguard Worker if (!allow_timezone_offset) {
872*8fb009dcSAndroid Build Coastguard Worker return 0;
873*8fb009dcSAndroid Build Coastguard Worker }
874*8fb009dcSAndroid Build Coastguard Worker int offset_hours, offset_minutes;
875*8fb009dcSAndroid Build Coastguard Worker if (!cbs_get_two_digits(©, &offset_hours) ||
876*8fb009dcSAndroid Build Coastguard Worker offset_hours > 23 || // Reject invalid hours.
877*8fb009dcSAndroid Build Coastguard Worker !cbs_get_two_digits(©, &offset_minutes) ||
878*8fb009dcSAndroid Build Coastguard Worker offset_minutes > 59) { // Reject invalid minutes.
879*8fb009dcSAndroid Build Coastguard Worker return 0;
880*8fb009dcSAndroid Build Coastguard Worker }
881*8fb009dcSAndroid Build Coastguard Worker offset_seconds = offset_sign * (offset_hours * 3600 + offset_minutes * 60);
882*8fb009dcSAndroid Build Coastguard Worker }
883*8fb009dcSAndroid Build Coastguard Worker
884*8fb009dcSAndroid Build Coastguard Worker if (CBS_len(©) != 0) {
885*8fb009dcSAndroid Build Coastguard Worker return 0; // Reject invalid lengths.
886*8fb009dcSAndroid Build Coastguard Worker }
887*8fb009dcSAndroid Build Coastguard Worker
888*8fb009dcSAndroid Build Coastguard Worker if (out_tm != NULL) {
889*8fb009dcSAndroid Build Coastguard Worker // Fill in the tm fields corresponding to what we validated.
890*8fb009dcSAndroid Build Coastguard Worker out_tm->tm_year = year - 1900;
891*8fb009dcSAndroid Build Coastguard Worker out_tm->tm_mon = month - 1;
892*8fb009dcSAndroid Build Coastguard Worker out_tm->tm_mday = day;
893*8fb009dcSAndroid Build Coastguard Worker out_tm->tm_hour = hour;
894*8fb009dcSAndroid Build Coastguard Worker out_tm->tm_min = min;
895*8fb009dcSAndroid Build Coastguard Worker out_tm->tm_sec = sec;
896*8fb009dcSAndroid Build Coastguard Worker if (offset_seconds && !OPENSSL_gmtime_adj(out_tm, 0, offset_seconds)) {
897*8fb009dcSAndroid Build Coastguard Worker return 0;
898*8fb009dcSAndroid Build Coastguard Worker }
899*8fb009dcSAndroid Build Coastguard Worker }
900*8fb009dcSAndroid Build Coastguard Worker return 1;
901*8fb009dcSAndroid Build Coastguard Worker }
902*8fb009dcSAndroid Build Coastguard Worker
CBS_parse_generalized_time(const CBS * cbs,struct tm * out_tm,int allow_timezone_offset)903*8fb009dcSAndroid Build Coastguard Worker int CBS_parse_generalized_time(const CBS *cbs, struct tm *out_tm,
904*8fb009dcSAndroid Build Coastguard Worker int allow_timezone_offset) {
905*8fb009dcSAndroid Build Coastguard Worker return CBS_parse_rfc5280_time_internal(cbs, 1, allow_timezone_offset, out_tm);
906*8fb009dcSAndroid Build Coastguard Worker }
907*8fb009dcSAndroid Build Coastguard Worker
CBS_parse_utc_time(const CBS * cbs,struct tm * out_tm,int allow_timezone_offset)908*8fb009dcSAndroid Build Coastguard Worker int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm,
909*8fb009dcSAndroid Build Coastguard Worker int allow_timezone_offset) {
910*8fb009dcSAndroid Build Coastguard Worker return CBS_parse_rfc5280_time_internal(cbs, 0, allow_timezone_offset, out_tm);
911*8fb009dcSAndroid Build Coastguard Worker }
912