Coverage Report

Created: 2026-09-03 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/simpletlv.c
Line
Count
Source
1
/*
2
 * simpletlv.c: Simple TLV encoding and decoding functions
3
 *
4
 * Copyright (C) 2016  Red Hat, Inc.
5
 *
6
 * Authors: Robert Relyea <rrelyea@redhat.com>
7
 *          Jakub Jelen <jjelen@redhat.com>
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
 */
23
24
#ifdef HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27
28
#include <stdio.h>
29
#include <string.h>
30
#include <ctype.h>
31
#include <assert.h>
32
#include <stdlib.h>
33
34
#include "internal.h"
35
#include "simpletlv.h"
36
37
/*
38
 * Put a tag/length record to a file in Simple TLV based on the  datalen
39
 * content length.
40
 */
41
int
42
sc_simpletlv_put_tag(u8 tag, size_t datalen, u8 *out, size_t outlen, u8 **ptr)
43
17.4k
{
44
17.4k
  u8 *p = out;
45
46
17.4k
  if (outlen < 2 || (outlen < 4 && datalen >= 0xff))
47
0
    return SC_ERROR_INVALID_ARGUMENTS;
48
49
  /* tag is just number between 0x01 and 0xFE */
50
17.4k
  if (tag == 0x00 || tag == 0xff)
51
6.37k
    return SC_ERROR_INVALID_ARGUMENTS;
52
11.0k
  if (datalen > 0xffff) {
53
    /* we can't store more than two bytes in Simple TLV */
54
0
    return SC_ERROR_WRONG_LENGTH;
55
0
  }
56
57
11.0k
  *p++ = tag; /* tag is single byte */
58
11.0k
  if (datalen < 0xff) {
59
    /* short value up to 255 */
60
10.7k
    *p++ = (u8)datalen; /* is in the second byte */
61
10.7k
  } else {
62
    /* longer values up to 65535 */
63
355
    *p++ = (u8)0xff; /* first byte is 0xff */
64
355
    *p++ = (u8)datalen & 0xff;
65
355
    *p++ = (u8)(datalen >> 8) & 0xff; /* LE */
66
355
  }
67
11.0k
  if (ptr != NULL)
68
11.0k
    *ptr = p;
69
11.0k
  return SC_SUCCESS;
70
11.0k
}
71
72
/* Read the TL file and return appropriate tag and the length of associated
73
 * content.
74
 */
75
int
76
sc_simpletlv_read_tag(const u8 **buf, size_t buflen, u8 *tag_out, size_t *taglen)
77
499k
{
78
499k
  u8 tag;
79
499k
  size_t left = buflen, len;
80
499k
  const u8 *p = *buf;
81
82
499k
  *buf = NULL;
83
84
499k
  if (left < 2) {
85
4.46k
    return SC_ERROR_INVALID_TLV_OBJECT;
86
4.46k
  }
87
495k
  tag = *p;
88
495k
  p++;
89
495k
  len = *p;
90
495k
  p++;
91
495k
  left -= 2;
92
93
495k
  if (len == 0xff) {
94
    /* don't crash on bad data */
95
8.87k
    if (left < 2) {
96
1.57k
      return SC_ERROR_INVALID_TLV_OBJECT;
97
1.57k
    }
98
    /* skip two bytes (the size) */
99
7.30k
    len = lebytes2ushort(p);
100
7.30k
    p += 2;
101
7.30k
    left -= 2;
102
7.30k
  }
103
104
493k
  *tag_out = tag;
105
493k
  *taglen = len;
106
493k
  *buf = p;
107
108
493k
  if (len > left)
109
34.5k
    return SC_ERROR_TLV_END_OF_CONTENTS;
110
111
459k
  return SC_SUCCESS;
112
493k
}