LCOV - code coverage report
Current view: top level - lib/util - asn1.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 470 634 74.1 %
Date: 2024-04-13 12:30:31 Functions: 52 56 92.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    simple ASN1 routines
       4             :    Copyright (C) Andrew Tridgell 2001
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "replace.h"
      21             : #include "system/locale.h"
      22             : #include "lib/util/asn1.h"
      23             : #include "lib/util/debug.h"
      24             : #include "lib/util/samba_util.h"
      25             : #include "lib/util/smb_strtox.h"
      26             : 
      27             : struct nesting {
      28             :         off_t start;
      29             :         size_t taglen; /* for parsing */
      30             :         struct nesting *next;
      31             : };
      32             : 
      33             : 
      34             : struct asn1_data {
      35             :         uint8_t *data;
      36             :         size_t length;
      37             :         off_t ofs;
      38             :         struct nesting *nesting;
      39             :         bool has_error;
      40             :         unsigned depth;
      41             :         unsigned max_depth;
      42             : };
      43             : 
      44             : /* allocate an asn1 structure */
      45     5336482 : struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx, unsigned max_depth)
      46             : {
      47     5336482 :         struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data);
      48     5336482 :         if (ret == NULL) {
      49           0 :                 DBG_ERR("asn1_init failed! out of memory\n");
      50           0 :                 return ret;
      51             :         }
      52     5336482 :         ret->max_depth = max_depth;
      53     5336482 :         return ret;
      54             : }
      55             : 
      56             : /* free an asn1 structure */
      57     4063080 : void asn1_free(struct asn1_data *data)
      58             : {
      59     4063080 :         talloc_free(data);
      60     4063080 : }
      61             : 
      62     4074614 : bool asn1_has_error(const struct asn1_data *data)
      63             : {
      64     4074614 :         return data->has_error;
      65             : }
      66             : 
      67         102 : void asn1_set_error(struct asn1_data *data)
      68             : {
      69         102 :         data->has_error = true;
      70         102 : }
      71             : 
      72     1985927 : bool asn1_has_nesting(const struct asn1_data *data)
      73             : {
      74     1985927 :         return data->nesting != NULL;
      75             : }
      76             : 
      77      522198 : off_t asn1_current_ofs(const struct asn1_data *data)
      78             : {
      79      522198 :         return data->ofs;
      80             : }
      81             : 
      82             : /* write to the ASN1 buffer, advancing the buffer pointer */
      83    89264882 : bool asn1_write(struct asn1_data *data, const void *p, int len)
      84             : {
      85    89264882 :         if (data->has_error) return false;
      86             : 
      87    89264882 :         if ((len < 0) || (data->ofs + (size_t)len < data->ofs)) {
      88           0 :                 data->has_error = true;
      89           0 :                 return false;
      90             :         }
      91             : 
      92    89264882 :         if (data->length < data->ofs+len) {
      93      206127 :                 uint8_t *newp;
      94    87972382 :                 newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len);
      95    87972382 :                 if (!newp) {
      96           0 :                         data->has_error = true;
      97           0 :                         return false;
      98             :                 }
      99    87972382 :                 data->data = newp;
     100    87972382 :                 data->length = data->ofs+len;
     101             :         }
     102    89264882 :         if (len > 0) {
     103    87972382 :                 memcpy(data->data + data->ofs, p, len);
     104    87972382 :                 data->ofs += len;
     105             :         }
     106    89056721 :         return true;
     107             : }
     108             : 
     109             : /* useful fn for writing a uint8_t */
     110    76185640 : bool asn1_write_uint8(struct asn1_data *data, uint8_t v)
     111             : {
     112    76185640 :         return asn1_write(data, &v, 1);
     113             : }
     114             : 
     115             : /* push a tag onto the asn1 data buffer. Used for nested structures */
     116    33163376 : bool asn1_push_tag(struct asn1_data *data, uint8_t tag)
     117             : {
     118       75210 :         struct nesting *nesting;
     119             : 
     120    33163376 :         if (!asn1_write_uint8(data, tag)) {
     121           0 :                 return false;
     122             :         }
     123    33163376 :         nesting = talloc(data, struct nesting);
     124    33163376 :         if (!nesting) {
     125           0 :                 data->has_error = true;
     126           0 :                 return false;
     127             :         }
     128             : 
     129    33163376 :         nesting->start = data->ofs;
     130    33163376 :         nesting->next = data->nesting;
     131    33163376 :         data->nesting = nesting;
     132    33163376 :         return asn1_write_uint8(data, 0xff);
     133             : }
     134             : 
     135             : /* pop a tag */
     136    33163376 : bool asn1_pop_tag(struct asn1_data *data)
     137             : {
     138       75210 :         struct nesting *nesting;
     139       75210 :         size_t len;
     140             : 
     141    33163376 :         if (data->has_error) {
     142           0 :                 return false;
     143             :         }
     144             : 
     145    33163376 :         nesting = data->nesting;
     146             : 
     147    33163376 :         if (!nesting) {
     148           0 :                 data->has_error = true;
     149           0 :                 return false;
     150             :         }
     151    33163376 :         len = data->ofs - (nesting->start+1);
     152             :         /* yes, this is ugly. We don't know in advance how many bytes the length
     153             :            of a tag will take, so we assumed 1 byte. If we were wrong then we
     154             :            need to correct our mistake */
     155    33163376 :         if (len > 0xFFFFFF) {
     156           0 :                 data->data[nesting->start] = 0x84;
     157           0 :                 if (!asn1_write_uint8(data, 0)) return false;
     158           0 :                 if (!asn1_write_uint8(data, 0)) return false;
     159           0 :                 if (!asn1_write_uint8(data, 0)) return false;
     160           0 :                 if (!asn1_write_uint8(data, 0)) return false;
     161           0 :                 memmove(data->data+nesting->start+5, data->data+nesting->start+1, len);
     162           0 :                 data->data[nesting->start+1] = (len>>24) & 0xFF;
     163           0 :                 data->data[nesting->start+2] = (len>>16) & 0xFF;
     164           0 :                 data->data[nesting->start+3] = (len>>8) & 0xFF;
     165           0 :                 data->data[nesting->start+4] = len&0xff;
     166    33163376 :         } else if (len > 0xFFFF) {
     167       16735 :                 data->data[nesting->start] = 0x83;
     168       16735 :                 if (!asn1_write_uint8(data, 0)) return false;
     169       16735 :                 if (!asn1_write_uint8(data, 0)) return false;
     170       16735 :                 if (!asn1_write_uint8(data, 0)) return false;
     171       16735 :                 memmove(data->data+nesting->start+4, data->data+nesting->start+1, len);
     172       16735 :                 data->data[nesting->start+1] = (len>>16) & 0xFF;
     173       16735 :                 data->data[nesting->start+2] = (len>>8) & 0xFF;
     174       16735 :                 data->data[nesting->start+3] = len&0xff;
     175    33146641 :         } else if (len > 255) {
     176     1192446 :                 data->data[nesting->start] = 0x82;
     177     1192446 :                 if (!asn1_write_uint8(data, 0)) return false;
     178     1192446 :                 if (!asn1_write_uint8(data, 0)) return false;
     179     1192446 :                 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
     180     1192446 :                 data->data[nesting->start+1] = len>>8;
     181     1192446 :                 data->data[nesting->start+2] = len&0xff;
     182    31954195 :         } else if (len > 127) {
     183     1362253 :                 data->data[nesting->start] = 0x81;
     184     1362253 :                 if (!asn1_write_uint8(data, 0)) return false;
     185     1362253 :                 memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
     186     1362253 :                 data->data[nesting->start+1] = len;
     187             :         } else {
     188    30591942 :                 data->data[nesting->start] = len;
     189             :         }
     190             : 
     191    33163376 :         data->nesting = nesting->next;
     192    33163376 :         talloc_free(nesting);
     193    33163376 :         return true;
     194             : }
     195             : 
     196             : /* "i" is the one's complement representation, as is the normal result of an
     197             :  * implicit signed->unsigned conversion */
     198             : 
     199     3786795 : static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative)
     200             : {
     201     3786795 :         uint8_t lowest = i & 0xFF;
     202             : 
     203     3786795 :         i = i >> 8;
     204     3786795 :         if (i != 0)
     205      619639 :                 if (!push_int_bigendian(data, i, negative))
     206           0 :                         return false;
     207             : 
     208     3786795 :         if (data->nesting->start+1 == data->ofs) {
     209             : 
     210             :                 /* We did not write anything yet, looking at the highest
     211             :                  * valued byte */
     212             : 
     213     3167165 :                 if (negative) {
     214             :                         /* Don't write leading 0xff's */
     215          18 :                         if (lowest == 0xFF)
     216           0 :                                 return true;
     217             : 
     218           9 :                         if ((lowest & 0x80) == 0) {
     219             :                                 /* The only exception for a leading 0xff is if
     220             :                                  * the highest bit is 0, which would indicate
     221             :                                  * a positive value */
     222           2 :                                 if (!asn1_write_uint8(data, 0xff))
     223           0 :                                         return false;
     224             :                         }
     225             :                 } else {
     226     3167147 :                         if (lowest & 0x80) {
     227             :                                 /* The highest bit of a positive integer is 1,
     228             :                                  * this would indicate a negative number. Push
     229             :                                  * a 0 to indicate a positive one */
     230       68216 :                                 if (!asn1_write_uint8(data, 0))
     231           0 :                                         return false;
     232             :                         }
     233             :                 }
     234             :         }
     235             : 
     236     3786786 :         return asn1_write_uint8(data, lowest);
     237             : }
     238             : 
     239             : /* write an Integer without the tag framing. Needed for example for the LDAP
     240             :  * Abandon Operation */
     241             : 
     242     3167157 : bool asn1_write_implicit_Integer(struct asn1_data *data, int i)
     243             : {
     244     3167157 :         if (data->has_error) {
     245           0 :                 return false;
     246             :         }
     247             : 
     248     3167157 :         if (i == -1) {
     249             :                 /* -1 is special as it consists of all-0xff bytes. In
     250             :                     push_int_bigendian this is the only case that is not
     251             :                     properly handled, as all 0xff bytes would be handled as
     252             :                     leading ones to be ignored. */
     253           1 :                 return asn1_write_uint8(data, 0xff);
     254             :         } else {
     255     3167156 :                 return push_int_bigendian(data, i, i<0);
     256             :         }
     257             : }
     258             : 
     259             : 
     260             : /* write an integer */
     261     3167077 : bool asn1_write_Integer(struct asn1_data *data, int i)
     262             : {
     263     3167077 :         if (!asn1_push_tag(data, ASN1_INTEGER)) return false;
     264     3167077 :         if (!asn1_write_implicit_Integer(data, i)) return false;
     265     3167077 :         return asn1_pop_tag(data);
     266             : }
     267             : 
     268             : /* write a BIT STRING */
     269           0 : bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding)
     270             : {
     271           0 :         if (!asn1_push_tag(data, ASN1_BIT_STRING)) return false;
     272           0 :         if (!asn1_write_uint8(data, padding)) return false;
     273           0 :         if (!asn1_write(data, p, length)) return false;
     274           0 :         return asn1_pop_tag(data);
     275             : }
     276             : 
     277    99598692 : bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID)
     278             : {
     279     1294015 :         unsigned int v, v2;
     280    99598692 :         const char *p = (const char *)OID;
     281     1294015 :         char *newp;
     282     1294015 :         int i;
     283    99598692 :         int error = 0;
     284             : 
     285    99598692 :         if (!isdigit(*p)) return false;
     286    99598690 :         v = smb_strtoul(p, &newp, 10, &error, SMB_STR_STANDARD);
     287    99598690 :         if (newp[0] != '.' || error != 0) {
     288           0 :                 return false;
     289             :         }
     290    99598690 :         p = newp + 1;
     291             : 
     292    99598690 :         if (!isdigit(*p)) return false;
     293    99598688 :         v2 = smb_strtoul(p, &newp, 10, &error, SMB_STR_STANDARD);
     294    99598688 :         if (newp[0] != '.' || error != 0) {
     295           0 :                 return false;
     296             :         }
     297    99598687 :         p = newp + 1;
     298             : 
     299             :         /*the ber representation can't use more space than the string one */
     300    99598687 :         *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID));
     301    99598687 :         if (!blob->data) return false;
     302             : 
     303    99598687 :         blob->data[0] = 40*v + v2;
     304             : 
     305    99598687 :         i = 1;
     306   480045114 :         while (*p) {
     307   380446429 :                 if (!isdigit(*p)) return false;
     308   380446428 :                 v = smb_strtoul(p, &newp, 10, &error, SMB_STR_STANDARD);
     309   380446428 :                 if (newp[0] == '.' || error != 0) {
     310   280847743 :                         p = newp + 1;
     311             :                         /* check for empty last component */
     312   280847743 :                         if (!*p) return false;
     313    99598685 :                 } else if (newp[0] == '\0') {
     314    98304677 :                         p = newp;
     315             :                 } else {
     316           0 :                         data_blob_free(blob);
     317           0 :                         return false;
     318             :                 }
     319   380446427 :                 if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f));
     320   380446427 :                 if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f));
     321   380446427 :                 if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f));
     322   380446427 :                 if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f));
     323   380446427 :                 blob->data[i++] = (v&0x7f);
     324             :         }
     325             : 
     326    99598685 :         blob->length = i;
     327             : 
     328    99598685 :         return true;
     329             : }
     330             : 
     331             : /**
     332             :  * Serialize partial OID string.
     333             :  * Partial OIDs are in the form:
     334             :  *   1:2.5.6:0x81
     335             :  *   1:2.5.6:0x8182
     336             :  */
     337       13078 : bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid)
     338             : {
     339       13078 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     340       13078 :         char *oid = talloc_strdup(tmp_ctx, partial_oid);
     341        1065 :         char *p;
     342             : 
     343             :         /* truncate partial part so ber_write_OID_String() works */
     344       13078 :         p = strchr(oid, ':');
     345       13078 :         if (p) {
     346           6 :                 *p = '\0';
     347           6 :                 p++;
     348             :         }
     349             : 
     350       13078 :         if (!ber_write_OID_String(mem_ctx, blob, oid)) {
     351           0 :                 talloc_free(tmp_ctx);
     352           0 :                 return false;
     353             :         }
     354             : 
     355             :         /* Add partially encoded sub-identifier */
     356       13078 :         if (p) {
     357           6 :                 DATA_BLOB tmp_blob = strhex_to_data_blob(tmp_ctx, p);
     358           6 :                 if (!data_blob_append(mem_ctx, blob, tmp_blob.data,
     359             :                                       tmp_blob.length)) {
     360           0 :                         talloc_free(tmp_ctx);
     361           0 :                         return false;
     362             :                 }
     363             :         }
     364             : 
     365       13078 :         talloc_free(tmp_ctx);
     366             : 
     367       13078 :         return true;
     368             : }
     369             : 
     370             : /* write an object ID to a ASN1 buffer */
     371      752530 : bool asn1_write_OID(struct asn1_data *data, const char *OID)
     372             : {
     373       20166 :         DATA_BLOB blob;
     374             : 
     375      752530 :         if (!asn1_push_tag(data, ASN1_OID)) return false;
     376             : 
     377      752530 :         if (!ber_write_OID_String(NULL, &blob, OID)) {
     378           0 :                 data->has_error = true;
     379           0 :                 return false;
     380             :         }
     381             : 
     382      752530 :         if (!asn1_write(data, blob.data, blob.length)) {
     383           0 :                 data_blob_free(&blob);
     384           0 :                 data->has_error = true;
     385           0 :                 return false;
     386             :         }
     387      752530 :         data_blob_free(&blob);
     388      752530 :         return asn1_pop_tag(data);
     389             : }
     390             : 
     391             : /* write an octet string */
     392    11593670 : bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length)
     393             : {
     394    11593670 :         if (!asn1_push_tag(data, ASN1_OCTET_STRING)) return false;
     395    11593670 :         if (!asn1_write(data, p, length)) return false;
     396    11593670 :         return asn1_pop_tag(data);
     397             : }
     398             : 
     399             : /* write a LDAP string */
     400      514867 : bool asn1_write_LDAPString(struct asn1_data *data, const char *s)
     401             : {
     402      514867 :         return asn1_write(data, s, strlen(s));
     403             : }
     404             : 
     405             : /* write a LDAP string from a DATA_BLOB */
     406       32733 : bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s)
     407             : {
     408       32733 :         return asn1_write(data, s->data, s->length);
     409             : }
     410             : 
     411             : /* write a general string */
     412           0 : bool asn1_write_GeneralString(struct asn1_data *data, const char *s)
     413             : {
     414           0 :         if (!asn1_push_tag(data, ASN1_GENERAL_STRING)) return false;
     415           0 :         if (!asn1_write_LDAPString(data, s)) return false;
     416           0 :         return asn1_pop_tag(data);
     417             : }
     418             : 
     419       35544 : bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
     420             : {
     421       35544 :         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
     422       35544 :         if (!asn1_write(data, blob->data, blob->length)) return false;
     423       35544 :         return asn1_pop_tag(data);
     424             : }
     425             : 
     426             : /* write a BOOLEAN */
     427      597251 : bool asn1_write_BOOLEAN(struct asn1_data *data, bool v)
     428             : {
     429      597251 :         if (!asn1_push_tag(data, ASN1_BOOLEAN)) return false;
     430      597658 :         if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false;
     431      597251 :         return asn1_pop_tag(data);
     432             : }
     433             : 
     434      600049 : bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v)
     435             : {
     436      600049 :         uint8_t tmp = 0;
     437      600049 :         if (!asn1_start_tag(data, ASN1_BOOLEAN)) return false;
     438      600049 :         *v = false;
     439      600049 :         if (!asn1_read_uint8(data, &tmp)) return false;
     440      600049 :         if (tmp == 0xFF) {
     441      246868 :                 *v = true;
     442             :         }
     443      600049 :         return asn1_end_tag(data);
     444             : }
     445             : 
     446             : /* write a BOOLEAN in a simple context */
     447          21 : bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context)
     448             : {
     449          21 :         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false;
     450          21 :         if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false;
     451          21 :         return asn1_pop_tag(data);
     452             : }
     453             : 
     454          21 : bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context)
     455             : {
     456          21 :         uint8_t tmp = 0;
     457          21 :         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false;
     458          21 :         *v = false;
     459          21 :         if (!asn1_read_uint8(data, &tmp)) return false;
     460          21 :         if (tmp == 0xFF) {
     461          21 :                 *v = true;
     462             :         }
     463          21 :         return asn1_end_tag(data);
     464             : }
     465             : 
     466             : /* check a BOOLEAN */
     467           0 : bool asn1_check_BOOLEAN(struct asn1_data *data, bool v)
     468             : {
     469           0 :         uint8_t b = 0;
     470             : 
     471           0 :         if (!asn1_read_uint8(data, &b)) return false;
     472           0 :         if (b != ASN1_BOOLEAN) {
     473           0 :                 data->has_error = true;
     474           0 :                 return false;
     475             :         }
     476           0 :         if (!asn1_read_uint8(data, &b)) return false;
     477           0 :         if (b != v) {
     478           0 :                 data->has_error = true;
     479           0 :                 return false;
     480             :         }
     481           0 :         return !data->has_error;
     482             : }
     483             : 
     484             : 
     485             : /* load a struct asn1_data structure with a lump of data, ready to be parsed */
     486      580284 : bool asn1_load(struct asn1_data *data, DATA_BLOB blob)
     487             : {
     488             :         /*
     489             :          * Save the maximum depth
     490             :          */
     491      580284 :         unsigned max_depth = data->max_depth;
     492             : 
     493      580284 :         ZERO_STRUCTP(data);
     494      580284 :         data->data = (uint8_t *)talloc_memdup(data, blob.data, blob.length);
     495      580284 :         if (!data->data) {
     496           0 :                 data->has_error = true;
     497           0 :                 return false;
     498             :         }
     499      580284 :         data->length = blob.length;
     500      580284 :         data->max_depth = max_depth;
     501      580284 :         return true;
     502             : }
     503             : 
     504             : /* Peek into an ASN1 buffer, not advancing the pointer */
     505   110703214 : bool asn1_peek(struct asn1_data *data, void *p, int len)
     506             : {
     507   110703214 :         if (data->has_error)
     508           0 :                 return false;
     509             : 
     510   110703214 :         if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
     511           0 :                 return false;
     512             : 
     513   110703214 :         if (data->ofs + len > data->length) {
     514             :                 /* we need to mark the buffer as consumed, so the caller knows
     515             :                    this was an out of data error, and not a decode error */
     516      166367 :                 data->ofs = data->length;
     517      166367 :                 return false;
     518             :         }
     519             : 
     520   110536847 :         memcpy(p, data->data + data->ofs, len);
     521   110536847 :         return true;
     522             : }
     523             : 
     524             : /* read from a ASN1 buffer, advancing the buffer pointer */
     525    98421019 : bool asn1_read(struct asn1_data *data, void *p, int len)
     526             : {
     527    98421019 :         if (!asn1_peek(data, p, len)) {
     528      166367 :                 data->has_error = true;
     529      166367 :                 return false;
     530             :         }
     531             : 
     532    98254652 :         data->ofs += len;
     533    98254652 :         return true;
     534             : }
     535             : 
     536             : /* read a uint8_t from a ASN1 buffer */
     537    85742499 : bool asn1_read_uint8(struct asn1_data *data, uint8_t *v)
     538             : {
     539    85742499 :         return asn1_read(data, v, 1);
     540             : }
     541             : 
     542    12282195 : bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v)
     543             : {
     544    12282195 :         return asn1_peek(data, v, 1);
     545             : }
     546             : 
     547    15065349 : bool asn1_peek_tag(struct asn1_data *data, uint8_t tag)
     548             : {
     549        7604 :         uint8_t b;
     550             : 
     551    15065349 :         if (asn1_tag_remaining(data) <= 0) {
     552     6611704 :                 return false;
     553             :         }
     554             : 
     555     8449303 :         if (!asn1_peek_uint8(data, &b))
     556           0 :                 return false;
     557             : 
     558     8449303 :         return (b == tag);
     559             : }
     560             : 
     561             : /*
     562             :  * just get the needed size the tag would consume
     563             :  */
     564     4521254 : static bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag,
     565             :                                       size_t *size)
     566             : {
     567     4521254 :         off_t start_ofs = data->ofs;
     568       11798 :         uint8_t b;
     569     4521254 :         size_t taglen = 0;
     570             : 
     571     4521254 :         if (data->has_error) {
     572           0 :                 return false;
     573             :         }
     574             : 
     575     4521254 :         if (!asn1_read_uint8(data, &b)) {
     576      166366 :                 data->ofs = start_ofs;
     577      166366 :                 data->has_error = false;
     578      166366 :                 return false;
     579             :         }
     580             : 
     581     4354888 :         if (b != tag) {
     582      147013 :                 data->ofs = start_ofs;
     583      147013 :                 data->has_error = false;
     584      147013 :                 return false;
     585             :         }
     586             : 
     587     4207875 :         if (!asn1_read_uint8(data, &b)) {
     588           0 :                 data->ofs = start_ofs;
     589           0 :                 data->has_error = false;
     590           0 :                 return false;
     591             :         }
     592             : 
     593     4207875 :         if (b & 0x80) {
     594     1606681 :                 int n = b & 0x7f;
     595     1606681 :                 if (!asn1_read_uint8(data, &b)) {
     596           0 :                         data->ofs = start_ofs;
     597           0 :                         data->has_error = false;
     598           0 :                         return false;
     599             :                 }
     600     1606681 :                 if (n > 4) {
     601             :                         /*
     602             :                          * We should not allow more than 4 bytes
     603             :                          * for the encoding of the tag length.
     604             :                          *
     605             :                          * Otherwise we'd overflow the taglen
     606             :                          * variable on 32 bit systems.
     607             :                          */
     608           0 :                         data->ofs = start_ofs;
     609           0 :                         data->has_error = false;
     610           0 :                         return false;
     611             :                 }
     612     1606681 :                 taglen = b;
     613     2220992 :                 while (n > 1) {
     614        1749 :                         size_t tmp_taglen;
     615             : 
     616      614311 :                         if (!asn1_read_uint8(data, &b)) {
     617           0 :                                 data->ofs = start_ofs;
     618           0 :                                 data->has_error = false;
     619           0 :                                 return false;
     620             :                         }
     621             : 
     622      614311 :                         tmp_taglen = (taglen << 8) | b;
     623             : 
     624      614311 :                         if ((tmp_taglen >> 8) != taglen) {
     625             :                                 /* overflow */
     626           0 :                                 data->ofs = start_ofs;
     627           0 :                                 data->has_error = false;
     628           0 :                                 return false;
     629             :                         }
     630      614311 :                         taglen = tmp_taglen;
     631             : 
     632      614311 :                         n--;
     633             :                 }
     634             :         } else {
     635     2601194 :                 taglen = b;
     636             :         }
     637             : 
     638     4207875 :         *size = (data->ofs - start_ofs) + taglen;
     639             : 
     640     4207875 :         data->ofs = start_ofs;
     641     4207875 :         data->has_error = false;
     642     4207875 :         return true;
     643             : }
     644             : 
     645             : /* start reading a nested asn1 structure */
     646    32463076 : bool asn1_start_tag(struct asn1_data *data, uint8_t tag)
     647             : {
     648       57772 :         uint8_t b;
     649       57772 :         struct nesting *nesting;
     650             : 
     651             :         /*
     652             :          * Check the depth of the parse tree and prevent it from growing
     653             :          * too large.
     654             :          */
     655    32463076 :         data->depth++;
     656    32463076 :         if (data->depth > data->max_depth) {
     657           2 :                 data->has_error = true;
     658           2 :                 return false;
     659             :         }
     660             : 
     661    32463074 :         if (!asn1_read_uint8(data, &b))
     662           0 :                 return false;
     663             : 
     664    32463073 :         if (b != tag) {
     665          38 :                 data->has_error = true;
     666          38 :                 return false;
     667             :         }
     668    32463035 :         nesting = talloc(data, struct nesting);
     669    32463035 :         if (!nesting) {
     670           0 :                 data->has_error = true;
     671           0 :                 return false;
     672             :         }
     673             : 
     674    32463035 :         if (!asn1_read_uint8(data, &b)) {
     675           0 :                 return false;
     676             :         }
     677             : 
     678    32463035 :         if (b & 0x80) {
     679     2571315 :                 int n = b & 0x7f;
     680     2571315 :                 if (!asn1_read_uint8(data, &b))
     681           0 :                         return false;
     682     2571315 :                 nesting->taglen = b;
     683     3794349 :                 while (n > 1) {
     684        6582 :                         size_t taglen;
     685             : 
     686     1223034 :                         if (!asn1_read_uint8(data, &b))
     687           0 :                                 return false;
     688             : 
     689     1223034 :                         taglen = (nesting->taglen << 8) | b;
     690             : 
     691     1223034 :                         if ((taglen >> 8) != nesting->taglen) {
     692             :                                 /* overflow */
     693           0 :                                 data->has_error = true;
     694           0 :                                 return false;
     695             :                         }
     696     1223034 :                         nesting->taglen = taglen;
     697             : 
     698     1223034 :                         n--;
     699             :                 }
     700             :         } else {
     701    29891720 :                 nesting->taglen = b;
     702             :         }
     703    32463035 :         nesting->start = data->ofs;
     704    32463035 :         nesting->next = data->nesting;
     705    32463035 :         data->nesting = nesting;
     706    32463035 :         if (asn1_tag_remaining(data) == -1) {
     707           0 :                 return false;
     708             :         }
     709    32463035 :         return !data->has_error;
     710             : }
     711             : 
     712             : /* stop reading a tag */
     713    32461346 : bool asn1_end_tag(struct asn1_data *data)
     714             : {
     715       57254 :         struct nesting *nesting;
     716             : 
     717    32461346 :         if (data->depth == 0) {
     718           0 :                 smb_panic("Unbalanced ASN.1 Tag nesting");
     719             :         }
     720    32461346 :         data->depth--;
     721             :         /* make sure we read it all */
     722    32461346 :         if (asn1_tag_remaining(data) != 0) {
     723           2 :                 data->has_error = true;
     724           2 :                 return false;
     725             :         }
     726             : 
     727    32461344 :         nesting = data->nesting;
     728             : 
     729    32461344 :         if (!nesting) {
     730           0 :                 data->has_error = true;
     731           0 :                 return false;
     732             :         }
     733             : 
     734    32461344 :         data->nesting = nesting->next;
     735    32461344 :         talloc_free(nesting);
     736    32461344 :         return true;
     737             : }
     738             : 
     739             : /* work out how many bytes are left in this nested tag */
     740   105886514 : int asn1_tag_remaining(struct asn1_data *data)
     741             : {
     742      176083 :         int remaining;
     743   105886514 :         if (data->has_error) {
     744           0 :                 return -1;
     745             :         }
     746             : 
     747   105886514 :         if (!data->nesting) {
     748           0 :                 data->has_error = true;
     749           0 :                 return -1;
     750             :         }
     751   105886514 :         remaining = data->nesting->taglen - (data->ofs - data->nesting->start);
     752   105886514 :         if (remaining > (data->length - data->ofs)) {
     753           0 :                 data->has_error = true;
     754           0 :                 return -1;
     755             :         }
     756   105886514 :         if (remaining < 0) {
     757           0 :                 data->has_error = true;
     758           0 :                 return -1;
     759             :         }
     760   105710431 :         return remaining;
     761             : }
     762             : 
     763             : /**
     764             :  * Internal implementation for reading binary OIDs
     765             :  * Reading is done as far in the buffer as valid OID
     766             :  * till buffer ends or not valid sub-identifier is found.
     767             :  */
     768    13908090 : static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
     769             :                                       char **OID, size_t *bytes_eaten)
     770             : {
     771      180611 :         int i;
     772      180611 :         uint8_t *b;
     773      180611 :         unsigned int v;
     774    13908090 :         char *tmp_oid = NULL;
     775             : 
     776    13908090 :         if (blob.length < 2) return false;
     777             : 
     778    13908090 :         b = blob.data;
     779             : 
     780    13908090 :         tmp_oid = talloc_asprintf(mem_ctx, "%u.%u", b[0]/40, b[0]%40);
     781    13908090 :         if (!tmp_oid) goto nomem;
     782             : 
     783    13908090 :         if (bytes_eaten != NULL) {
     784    13908090 :                 *bytes_eaten = 0;
     785             :         }
     786             : 
     787   118830737 :         for(i = 1, v = 0; i < blob.length; i++) {
     788   104922647 :                 v = (v<<7) | (b[i]&0x7f);
     789   104922647 :                 if ( ! (b[i] & 0x80)) {
     790    63614999 :                         tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  v);
     791    63614999 :                         v = 0;
     792    63614999 :                         if (bytes_eaten)
     793    63614999 :                                 *bytes_eaten = i+1;
     794             :                 }
     795   104922647 :                 if (!tmp_oid) goto nomem;
     796             :         }
     797             : 
     798    13908090 :         *OID = tmp_oid;
     799    13908090 :         return true;
     800             : 
     801           0 : nomem:
     802           0 :         return false;
     803             : }
     804             : 
     805             : /* read an object ID from a data blob */
     806    13906047 : bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID)
     807             : {
     808      180431 :         size_t bytes_eaten;
     809             : 
     810    13906047 :         if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten))
     811           0 :                 return false;
     812             : 
     813    13906047 :         return (bytes_eaten == blob.length);
     814             : }
     815             : 
     816             : /**
     817             :  * Deserialize partial OID string.
     818             :  * Partial OIDs are in the form:
     819             :  *   1:2.5.6:0x81
     820             :  *   1:2.5.6:0x8182
     821             :  */
     822        2043 : bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
     823             :                                  char **partial_oid)
     824             : {
     825         180 :         size_t bytes_left;
     826         180 :         size_t bytes_eaten;
     827        2043 :         char *identifier = NULL;
     828        2043 :         char *tmp_oid = NULL;
     829             : 
     830        2043 :         if (!_ber_read_OID_String_impl(mem_ctx, blob, &tmp_oid, &bytes_eaten))
     831           0 :                 return false;
     832             : 
     833        2043 :         if (bytes_eaten < blob.length) {
     834          46 :                 bytes_left = blob.length - bytes_eaten;
     835          46 :                 identifier = hex_encode_talloc(mem_ctx, &blob.data[bytes_eaten], bytes_left);
     836          46 :                 if (!identifier)        goto nomem;
     837             : 
     838          46 :                 *partial_oid = talloc_asprintf_append_buffer(tmp_oid, ":0x%s", identifier);
     839          46 :                 if (!*partial_oid)      goto nomem;
     840          46 :                 TALLOC_FREE(identifier);
     841             :         } else {
     842        1997 :                 *partial_oid = tmp_oid;
     843             :         }
     844             : 
     845        1863 :         return true;
     846             : 
     847           0 : nomem:
     848           0 :         TALLOC_FREE(identifier);
     849           0 :         TALLOC_FREE(tmp_oid);
     850           0 :         return false;
     851             : }
     852             : 
     853             : /* read an object ID from a ASN1 buffer */
     854      372158 : bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID)
     855             : {
     856        9135 :         DATA_BLOB blob;
     857        9135 :         int len;
     858             : 
     859      372158 :         if (!asn1_start_tag(data, ASN1_OID)) return false;
     860             : 
     861      372158 :         len = asn1_tag_remaining(data);
     862      372158 :         if (len < 0) {
     863           0 :                 data->has_error = true;
     864           0 :                 return false;
     865             :         }
     866             : 
     867      372158 :         blob = data_blob(NULL, len);
     868      372158 :         if (!blob.data) {
     869           0 :                 data->has_error = true;
     870           0 :                 return false;
     871             :         }
     872             : 
     873      372158 :         if (!asn1_read(data, blob.data, len)) return false;
     874      372158 :         if (!asn1_end_tag(data)) {
     875           0 :                 data_blob_free(&blob);
     876           0 :                 return false;
     877             :         }
     878             : 
     879      372158 :         if (!ber_read_OID_String(mem_ctx, blob, OID)) {
     880           0 :                 data->has_error = true;
     881           0 :                 data_blob_free(&blob);
     882           0 :                 return false;
     883             :         }
     884             : 
     885      372158 :         data_blob_free(&blob);
     886      372158 :         return true;
     887             : }
     888             : 
     889             : /* check that the next object ID is correct */
     890      107541 : bool asn1_check_OID(struct asn1_data *data, const char *OID)
     891             : {
     892        2136 :         char *id;
     893             : 
     894      107541 :         if (!asn1_read_OID(data, data, &id)) return false;
     895             : 
     896      107541 :         if (strcmp(id, OID) != 0) {
     897          45 :                 talloc_free(id);
     898          45 :                 data->has_error = true;
     899          45 :                 return false;
     900             :         }
     901      107496 :         talloc_free(id);
     902      107496 :         return true;
     903             : }
     904             : 
     905             : /* read a LDAPString from a ASN1 buffer */
     906      587992 : bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
     907             : {
     908        1703 :         int len;
     909      587992 :         len = asn1_tag_remaining(data);
     910      587992 :         if (len < 0) {
     911           0 :                 data->has_error = true;
     912           0 :                 return false;
     913             :         }
     914      587992 :         *s = talloc_array(mem_ctx, char, len+1);
     915      587992 :         if (! *s) {
     916           0 :                 data->has_error = true;
     917           0 :                 return false;
     918             :         }
     919      587992 :         (*s)[len] = 0;
     920      587992 :         return asn1_read(data, *s, len);
     921             : }
     922             : 
     923             : 
     924             : /* read a GeneralString from a ASN1 buffer */
     925       38607 : bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
     926             : {
     927       38607 :         if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false;
     928       38607 :         if (!asn1_read_LDAPString(data, mem_ctx, s)) return false;
     929       38607 :         return asn1_end_tag(data);
     930             : }
     931             : 
     932             : 
     933             : /* read a octet string blob */
     934    11584808 : bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
     935             : {
     936        9684 :         int len;
     937    11584808 :         ZERO_STRUCTP(blob);
     938    11584808 :         if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false;
     939    11584808 :         len = asn1_tag_remaining(data);
     940    11584808 :         if (len < 0) {
     941           0 :                 data->has_error = true;
     942           0 :                 return false;
     943             :         }
     944    11584808 :         *blob = data_blob_talloc(mem_ctx, NULL, len+1);
     945    11584808 :         if (!blob->data || blob->length < len) {
     946           0 :                 data->has_error = true;
     947           0 :                 return false;
     948             :         }
     949    11584808 :         if (!asn1_read(data, blob->data, len)) goto err;
     950    11584808 :         if (!asn1_end_tag(data)) goto err;
     951    11584808 :         blob->length--;
     952    11584808 :         blob->data[len] = 0;
     953    11584808 :         return true;
     954             : 
     955           0 :   err:
     956             : 
     957           0 :         data_blob_free(blob);
     958           0 :         *blob = data_blob_null;
     959           0 :         return false;
     960             : }
     961             : 
     962       58008 : bool asn1_read_ContextSimple(struct asn1_data *data, TALLOC_CTX *mem_ctx, uint8_t num,
     963             :                              DATA_BLOB *blob)
     964             : {
     965         123 :         int len;
     966       58008 :         ZERO_STRUCTP(blob);
     967       58008 :         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
     968       58008 :         len = asn1_tag_remaining(data);
     969       58008 :         if (len < 0) {
     970           0 :                 data->has_error = true;
     971           0 :                 return false;
     972             :         }
     973       58008 :         *blob = data_blob_talloc(mem_ctx, NULL, len + 1);
     974       58008 :         if ((len != 0) && (!blob->data)) {
     975           0 :                 data->has_error = true;
     976           0 :                 return false;
     977             :         }
     978       58008 :         if (!asn1_read(data, blob->data, len)) return false;
     979       58008 :         blob->length--;
     980       58008 :         blob->data[len] = 0;
     981       58008 :         return asn1_end_tag(data);
     982             : }
     983             : 
     984             : /* read an integer without tag*/
     985     3169949 : bool asn1_read_implicit_Integer(struct asn1_data *data, int *i)
     986             : {
     987        2926 :         uint8_t b;
     988     3169949 :         uint32_t x = 0;
     989     3169949 :         bool first_byte = true;
     990             : 
     991     3169949 :         *i = 0;
     992             : 
     993     7030818 :         while (!data->has_error && asn1_tag_remaining(data)>0) {
     994     3860869 :                 if (!asn1_read_uint8(data, &b)) return false;
     995     3860869 :                 if (first_byte) {
     996     3169949 :                         if (b & 0x80) {
     997             :                                 /* Number is negative. */
     998          10 :                                 x = (uint32_t)-1;
     999             :                         }
    1000     3167023 :                         first_byte = false;
    1001             :                 }
    1002     3860869 :                 x = (x << 8) + b;
    1003             :         }
    1004     3169949 :         *i = (int)x;
    1005             : 
    1006     3169949 :         return !data->has_error;
    1007             : }
    1008             : 
    1009             : /* read an integer */
    1010     3169869 : bool asn1_read_Integer(struct asn1_data *data, int *i)
    1011             : {
    1012     3169869 :         *i = 0;
    1013             : 
    1014     3169869 :         if (!asn1_start_tag(data, ASN1_INTEGER)) return false;
    1015     3169869 :         if (!asn1_read_implicit_Integer(data, i)) return false;
    1016     3169869 :         return asn1_end_tag(data);
    1017             : }
    1018             : 
    1019             : /* read a BIT STRING */
    1020           0 : bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding)
    1021             : {
    1022           0 :         int len;
    1023           0 :         ZERO_STRUCTP(blob);
    1024           0 :         if (!asn1_start_tag(data, ASN1_BIT_STRING)) return false;
    1025           0 :         len = asn1_tag_remaining(data);
    1026           0 :         if (len < 0) {
    1027           0 :                 data->has_error = true;
    1028           0 :                 return false;
    1029             :         }
    1030           0 :         if (!asn1_read_uint8(data, padding)) return false;
    1031             : 
    1032           0 :         *blob = data_blob_talloc(mem_ctx, NULL, len+1);
    1033           0 :         if (!blob->data || blob->length < len) {
    1034           0 :                 data->has_error = true;
    1035           0 :                 return false;
    1036             :         }
    1037           0 :         if (asn1_read(data, blob->data, len - 1)) {
    1038           0 :                 blob->length--;
    1039           0 :                 blob->data[len] = 0;
    1040           0 :                 asn1_end_tag(data);
    1041             :         }
    1042             : 
    1043           0 :         if (data->has_error) {
    1044           0 :                 data_blob_free(blob);
    1045           0 :                 *blob = data_blob_null;
    1046           0 :                 *padding = 0;
    1047           0 :                 return false;
    1048             :         }
    1049           0 :         return true;
    1050             : }
    1051             : 
    1052             : /* read a non-negative enumerated value */
    1053     1487425 : bool asn1_read_enumerated(struct asn1_data *data, int *v)
    1054             : {
    1055     1487425 :         unsigned int val_will_wrap = (0xFFU << ((sizeof(int)*8)-8));
    1056     1487425 :         *v = 0;
    1057             : 
    1058     1487425 :         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
    1059     2974850 :         while (!data->has_error && asn1_tag_remaining(data)>0) {
    1060        1782 :                 uint8_t b;
    1061     1487425 :                 if (!asn1_read_uint8(data, &b)) {
    1062           0 :                         return false;
    1063             :                 }
    1064     1487425 :                 if (*v & val_will_wrap) {
    1065             :                         /*
    1066             :                          * There is something already in
    1067             :                          * the top byte of the int. If we
    1068             :                          * shift left by 8 it's going to
    1069             :                          * wrap. Prevent this.
    1070             :                          */
    1071           0 :                         data->has_error = true;
    1072           0 :                         return false;
    1073             :                 }
    1074             :                 /*
    1075             :                  * To please/fool the Undefined Behaviour Sanitizer we cast to
    1076             :                  * unsigned for the left shift.
    1077             :                  */
    1078     1487425 :                 *v = ((unsigned int)*v << 8) + b;
    1079     1487425 :                 if (*v < 0) {
    1080             :                         /* ASN1_ENUMERATED can't be -ve. */
    1081           0 :                         data->has_error = true;
    1082           0 :                         return false;
    1083             :                 }
    1084             :         }
    1085     1487425 :         return asn1_end_tag(data);
    1086             : }
    1087             : 
    1088             : /* write an enumerated value to the stream */
    1089     1591501 : bool asn1_write_enumerated(struct asn1_data *data, uint8_t v)
    1090             : {
    1091     1591501 :         if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false;
    1092     1591501 :         if (!asn1_write_uint8(data, v)) return false;
    1093     1591501 :         return asn1_pop_tag(data);
    1094             : }
    1095             : 
    1096             : /*
    1097             :   Get us the data just written without copying
    1098             : */
    1099     2773941 : bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob)
    1100             : {
    1101     2773941 :         if (asn1->has_error) {
    1102           0 :                 return false;
    1103             :         }
    1104     2773941 :         if (asn1->nesting != NULL) {
    1105           0 :                 return false;
    1106             :         }
    1107     2773941 :         blob->data = asn1->data;
    1108     2773941 :         blob->length = asn1->length;
    1109     2773941 :         return true;
    1110             : }
    1111             : 
    1112     2773718 : bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
    1113             :                        DATA_BLOB *pblob)
    1114             : {
    1115        9684 :         DATA_BLOB blob;
    1116             : 
    1117     2773718 :         if (!asn1_blob(asn1, &blob)) {
    1118           0 :                 return false;
    1119             :         }
    1120             : 
    1121     2773718 :         *pblob = (DATA_BLOB) { .length = blob.length };
    1122     2773718 :         pblob->data = talloc_move(mem_ctx, &blob.data);
    1123             : 
    1124             :         /*
    1125             :          * Stop access from here on
    1126             :          */
    1127     2773718 :         asn1->has_error = true;
    1128             : 
    1129     2773718 :         return true;
    1130             : }
    1131             : 
    1132             : /*
    1133             :   Fill in an asn1 struct without making a copy
    1134             : */
    1135     1984452 : void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len)
    1136             : {
    1137             :         /*
    1138             :          * Save max_depth
    1139             :          */
    1140     1984452 :         unsigned max_depth = data->max_depth;
    1141     1984452 :         ZERO_STRUCTP(data);
    1142     1984452 :         data->data = buf;
    1143     1984452 :         data->length = len;
    1144     1984452 :         data->max_depth = max_depth;
    1145     1984452 : }
    1146             : 
    1147     4521254 : int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
    1148             : {
    1149       11798 :         struct asn1_data asn1;
    1150       11798 :         size_t size;
    1151       11798 :         bool ok;
    1152             : 
    1153     4521254 :         ZERO_STRUCT(asn1);
    1154     4521254 :         asn1.data = blob.data;
    1155     4521254 :         asn1.length = blob.length;
    1156             : 
    1157     4521254 :         ok = asn1_peek_tag_needed_size(&asn1, tag, &size);
    1158     4521254 :         if (!ok) {
    1159      308873 :                 return EMSGSIZE;
    1160             :         }
    1161             : 
    1162     4207875 :         if (size > blob.length) {
    1163     1976929 :                 *packet_size = size;
    1164     1976929 :                 return EAGAIN;
    1165             :         }
    1166             : 
    1167     2230946 :         *packet_size = size;
    1168     2230946 :         return 0;
    1169             : }
    1170             : 
    1171             : /*
    1172             :  * Get the length of the ASN.1 data
    1173             :  */
    1174      353185 : size_t asn1_get_length(const struct asn1_data *asn1) {
    1175      353185 :         return asn1->length;
    1176             : }

Generated by: LCOV version 1.14