blob: 2d81a6e1371058ddecfe9f2f008ea7dc4ab5eecc [file] [log] [blame]
Kenny Root7a4adb52013-10-09 10:14:35 -07001/*
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
xunchang24788852019-03-22 16:08:52 -070017#include "private/asn1_decoder.h"
Kenny Root7a4adb52013-10-09 10:14:35 -070018
Tao Bao861c53c2017-03-20 17:09:13 -070019int asn1_context::peek_byte() const {
Mikhail Lappo8524fad2017-03-23 17:07:39 +010020 if (length_ == 0) {
Tao Bao861c53c2017-03-20 17:09:13 -070021 return -1;
22 }
23 return *p_;
Kenny Root7a4adb52013-10-09 10:14:35 -070024}
25
Tao Bao861c53c2017-03-20 17:09:13 -070026int asn1_context::get_byte() {
Mikhail Lappo8524fad2017-03-23 17:07:39 +010027 if (length_ == 0) {
Tao Bao861c53c2017-03-20 17:09:13 -070028 return -1;
29 }
30
31 int byte = *p_;
32 p_++;
33 length_--;
34 return byte;
Kenny Root7a4adb52013-10-09 10:14:35 -070035}
36
Tao Bao861c53c2017-03-20 17:09:13 -070037bool 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;
Kenny Root7a4adb52013-10-09 10:14:35 -070044}
45
Tao Bao861c53c2017-03-20 17:09:13 -070046bool 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;
Kenny Root7a4adb52013-10-09 10:14:35 -070053 return true;
Tao Bao861c53c2017-03-20 17:09:13 -070054 }
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;
Kenny Root7a4adb52013-10-09 10:14:35 -070064 }
Tao Bao861c53c2017-03-20 17:09:13 -070065 length <<= 8;
66 length += byte;
67 }
68 *out_len = length;
69 return true;
Kenny Root7a4adb52013-10-09 10:14:35 -070070}
71
72/**
73 * Returns the constructed type and advances the pointer. E.g. A0 -> 0
74 */
Tao Bao861c53c2017-03-20 17:09:13 -070075asn1_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);
Kenny Root7a4adb52013-10-09 10:14:35 -070093 size_t length;
Tao Bao861c53c2017-03-20 17:09:13 -070094 if (!decode_length(&length) || !skip_bytes(length)) {
95 return false;
Kenny Root7a4adb52013-10-09 10:14:35 -070096 }
Tao Bao861c53c2017-03-20 17:09:13 -070097 byte = peek_byte();
98 }
99 return byte != -1;
Kenny Root7a4adb52013-10-09 10:14:35 -0700100}
101
Tao Bao861c53c2017-03-20 17:09:13 -0700102int asn1_context::asn1_constructed_type() const {
103 return app_type_;
Kenny Root7a4adb52013-10-09 10:14:35 -0700104}
105
Tao Bao861c53c2017-03-20 17:09:13 -0700106asn1_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);
Kenny Root7a4adb52013-10-09 10:14:35 -0700115}
116
Tao Bao861c53c2017-03-20 17:09:13 -0700117asn1_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);
Kenny Root7a4adb52013-10-09 10:14:35 -0700126}
127
Tao Bao861c53c2017-03-20 17:09:13 -0700128bool 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;
Kenny Root7a4adb52013-10-09 10:14:35 -0700134}
135
Tao Bao861c53c2017-03-20 17:09:13 -0700136bool 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;
Kenny Root7a4adb52013-10-09 10:14:35 -0700145}
146
Tao Bao861c53c2017-03-20 17:09:13 -0700147bool 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;
Kenny Root7a4adb52013-10-09 10:14:35 -0700156}