• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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