Home | History | Annotate | Download | only in recovery
      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 "asn1_decoder.h"
     18 
     19 #include <stdint.h>
     20 
     21 int asn1_context::peek_byte() const {
     22   if (length_ == 0) {
     23     return -1;
     24   }
     25   return *p_;
     26 }
     27 
     28 int asn1_context::get_byte() {
     29   if (length_ == 0) {
     30     return -1;
     31   }
     32 
     33   int byte = *p_;
     34   p_++;
     35   length_--;
     36   return byte;
     37 }
     38 
     39 bool asn1_context::skip_bytes(size_t num_skip) {
     40   if (length_ < num_skip) {
     41     return false;
     42   }
     43   p_ += num_skip;
     44   length_ -= num_skip;
     45   return true;
     46 }
     47 
     48 bool asn1_context::decode_length(size_t* out_len) {
     49   int num_octets = get_byte();
     50   if (num_octets == -1) {
     51     return false;
     52   }
     53   if ((num_octets & 0x80) == 0x00) {
     54     *out_len = num_octets;
     55     return true;
     56   }
     57   num_octets &= kMaskTag;
     58   if (static_cast<size_t>(num_octets) >= sizeof(size_t)) {
     59     return false;
     60   }
     61   size_t length = 0;
     62   for (int i = 0; i < num_octets; ++i) {
     63     int byte = get_byte();
     64     if (byte == -1) {
     65       return false;
     66     }
     67     length <<= 8;
     68     length += byte;
     69   }
     70   *out_len = length;
     71   return true;
     72 }
     73 
     74 /**
     75  * Returns the constructed type and advances the pointer. E.g. A0 -> 0
     76  */
     77 asn1_context* asn1_context::asn1_constructed_get() {
     78   int type = get_byte();
     79   if (type == -1 || (type & kMaskConstructed) != kTagConstructed) {
     80     return nullptr;
     81   }
     82   size_t length;
     83   if (!decode_length(&length) || length > length_) {
     84     return nullptr;
     85   }
     86   asn1_context* app_ctx = new asn1_context(p_, length);
     87   app_ctx->app_type_ = type & kMaskAppType;
     88   return app_ctx;
     89 }
     90 
     91 bool asn1_context::asn1_constructed_skip_all() {
     92   int byte = peek_byte();
     93   while (byte != -1 && (byte & kMaskConstructed) == kTagConstructed) {
     94     skip_bytes(1);
     95     size_t length;
     96     if (!decode_length(&length) || !skip_bytes(length)) {
     97       return false;
     98     }
     99     byte = peek_byte();
    100   }
    101   return byte != -1;
    102 }
    103 
    104 int asn1_context::asn1_constructed_type() const {
    105   return app_type_;
    106 }
    107 
    108 asn1_context* asn1_context::asn1_sequence_get() {
    109   if ((get_byte() & kMaskTag) != kTagSequence) {
    110     return nullptr;
    111   }
    112   size_t length;
    113   if (!decode_length(&length) || length > length_) {
    114     return nullptr;
    115   }
    116   return new asn1_context(p_, length);
    117 }
    118 
    119 asn1_context* asn1_context::asn1_set_get() {
    120   if ((get_byte() & kMaskTag) != kTagSet) {
    121     return nullptr;
    122   }
    123   size_t length;
    124   if (!decode_length(&length) || length > length_) {
    125     return nullptr;
    126   }
    127   return new asn1_context(p_, length);
    128 }
    129 
    130 bool asn1_context::asn1_sequence_next() {
    131   size_t length;
    132   if (get_byte() == -1 || !decode_length(&length) || !skip_bytes(length)) {
    133     return false;
    134   }
    135   return true;
    136 }
    137 
    138 bool asn1_context::asn1_oid_get(const uint8_t** oid, size_t* length) {
    139   if (get_byte() != kTagOid) {
    140     return false;
    141   }
    142   if (!decode_length(length) || *length == 0 || *length > length_) {
    143     return false;
    144   }
    145   *oid = p_;
    146   return true;
    147 }
    148 
    149 bool asn1_context::asn1_octet_string_get(const uint8_t** octet_string, size_t* length) {
    150   if (get_byte() != kTagOctetString) {
    151     return false;
    152   }
    153   if (!decode_length(length) || *length == 0 || *length > length_) {
    154     return false;
    155   }
    156   *octet_string = p_;
    157   return true;
    158 }
    159