blob: 2d81a6e1371058ddecfe9f2f008ea7dc4ab5eecc [file] [log] [blame]
bigbiffd58ba182020-03-23 10:02:29 -04001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
bigbiff1f9e4842020-10-31 11:33:15 -040017#include "private/asn1_decoder.h"
bigbiffd58ba182020-03-23 10:02:29 -040018
19int asn1_context::peek_byte() const {
20 if (length_ == 0) {
21 return -1;
22 }
23 return *p_;
24}
25
26int asn1_context::get_byte() {
27 if (length_ == 0) {
28 return -1;
29 }
30
31 int byte = *p_;
32 p_++;
33 length_--;
34 return byte;
35}
36
37bool asn1_context::skip_bytes(size_t num_skip) {
38 if (length_ < num_skip) {
39 return false;
40 }
41 p_ += num_skip;
42 length_ -= num_skip;
43 return true;
44}
45
46bool asn1_context::decode_length(size_t* out_len) {
47 int num_octets = get_byte();
48 if (num_octets == -1) {
49 return false;
50 }
51 if ((num_octets & 0x80) == 0x00) {
52 *out_len = num_octets;
53 return true;
54 }
55 num_octets &= kMaskTag;
56 if (static_cast<size_t>(num_octets) >= sizeof(size_t)) {
57 return false;
58 }
59 size_t length = 0;
60 for (int i = 0; i < num_octets; ++i) {
61 int byte = get_byte();
62 if (byte == -1) {
63 return false;
64 }
65 length <<= 8;
66 length += byte;
67 }
68 *out_len = length;
69 return true;
70}
71
72/**
73 * Returns the constructed type and advances the pointer. E.g. A0 -> 0
74 */
75asn1_context* asn1_context::asn1_constructed_get() {
76 int type = get_byte();
77 if (type == -1 || (type & kMaskConstructed) != kTagConstructed) {
78 return nullptr;
79 }
80 size_t length;
81 if (!decode_length(&length) || length > length_) {
82 return nullptr;
83 }
84 asn1_context* app_ctx = new asn1_context(p_, length);
85 app_ctx->app_type_ = type & kMaskAppType;
86 return app_ctx;
87}
88
89bool asn1_context::asn1_constructed_skip_all() {
90 int byte = peek_byte();
91 while (byte != -1 && (byte & kMaskConstructed) == kTagConstructed) {
92 skip_bytes(1);
93 size_t length;
94 if (!decode_length(&length) || !skip_bytes(length)) {
95 return false;
96 }
97 byte = peek_byte();
98 }
99 return byte != -1;
100}
101
102int asn1_context::asn1_constructed_type() const {
103 return app_type_;
104}
105
106asn1_context* asn1_context::asn1_sequence_get() {
107 if ((get_byte() & kMaskTag) != kTagSequence) {
108 return nullptr;
109 }
110 size_t length;
111 if (!decode_length(&length) || length > length_) {
112 return nullptr;
113 }
114 return new asn1_context(p_, length);
115}
116
117asn1_context* asn1_context::asn1_set_get() {
118 if ((get_byte() & kMaskTag) != kTagSet) {
119 return nullptr;
120 }
121 size_t length;
122 if (!decode_length(&length) || length > length_) {
123 return nullptr;
124 }
125 return new asn1_context(p_, length);
126}
127
128bool asn1_context::asn1_sequence_next() {
129 size_t length;
130 if (get_byte() == -1 || !decode_length(&length) || !skip_bytes(length)) {
131 return false;
132 }
133 return true;
134}
135
136bool asn1_context::asn1_oid_get(const uint8_t** oid, size_t* length) {
137 if (get_byte() != kTagOid) {
138 return false;
139 }
140 if (!decode_length(length) || *length == 0 || *length > length_) {
141 return false;
142 }
143 *oid = p_;
144 return true;
145}
146
147bool asn1_context::asn1_octet_string_get(const uint8_t** octet_string, size_t* length) {
148 if (get_byte() != kTagOctetString) {
149 return false;
150 }
151 if (!decode_length(length) || *length == 0 || *length > length_) {
152 return false;
153 }
154 *octet_string = p_;
155 return true;
156}