1 /*
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
17 #include "private/asn1_decoder.h"
18
peek_byte() const19 int asn1_context::peek_byte() const {
20 if (length_ == 0) {
21 return -1;
22 }
23 return *p_;
24 }
25
get_byte()26 int 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
skip_bytes(size_t num_skip)37 bool 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
decode_length(size_t * out_len)46 bool 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 */
asn1_constructed_get()75 asn1_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
asn1_constructed_skip_all()89 bool 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
asn1_constructed_type() const102 int asn1_context::asn1_constructed_type() const {
103 return app_type_;
104 }
105
asn1_sequence_get()106 asn1_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
asn1_set_get()117 asn1_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
asn1_sequence_next()128 bool 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
asn1_oid_get(const uint8_t ** oid,size_t * length)136 bool 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
asn1_octet_string_get(const uint8_t ** octet_string,size_t * length)147 bool 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 }
157