Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18826433
ber-help.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
11 KB
Subscribers
None
ber-help.c
View Options
/* ber-help.c - BER herlper functions
* Copyright (C) 2001, 2012 g10 Code GmbH
*
* This file is part of KSBA.
*
* KSBA is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* KSBA is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copies of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, see <http://www.gnu.org/licenses/>.
*/
#include
<config.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<assert.h>
#include
"util.h"
#include
"asn1-func.h"
/* need some constants */
#include
"ber-help.h"
/* Fixme: The parser functions should check that primitive types don't
have the constructed bit set (which is not allowed). This saves us
some work when using these parsers */
static
int
read_byte
(
ksba_reader_t
reader
)
{
unsigned
char
buf
;
size_t
nread
;
int
rc
;
do
rc
=
ksba_reader_read
(
reader
,
&
buf
,
1
,
&
nread
);
while
(
!
rc
&&
!
nread
);
return
rc
?
-1
:
buf
;
}
static
int
premature_eof
(
struct
tag_info
*
ti
)
{
/* Note: We do an strcmp on this string at othyer places. */
ti
->
err_string
=
"premature EOF"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
static
gpg_error_t
eof_or_error
(
ksba_reader_t
reader
,
struct
tag_info
*
ti
,
int
premature
)
{
gpg_error_t
err
;
err
=
ksba_reader_error
(
reader
);
if
(
err
)
{
ti
->
err_string
=
"read error"
;
return
err
;
}
if
(
premature
)
return
premature_eof
(
ti
);
return
gpg_error
(
GPG_ERR_EOF
);
}
/*
Read the tag and the length part from the TLV triplet.
*/
gpg_error_t
_ksba_ber_read_tl
(
ksba_reader_t
reader
,
struct
tag_info
*
ti
)
{
int
c
;
unsigned
long
tag
;
ti
->
length
=
0
;
ti
->
ndef
=
0
;
ti
->
nhdr
=
0
;
ti
->
err_string
=
NULL
;
ti
->
non_der
=
0
;
/* Get the tag */
c
=
read_byte
(
reader
);
if
(
c
==
-1
)
return
eof_or_error
(
reader
,
ti
,
0
);
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
ti
->
class
=
(
c
&
0xc0
)
>>
6
;
ti
->
is_constructed
=
!!
(
c
&
0x20
);
tag
=
c
&
0x1f
;
if
(
tag
==
0x1f
)
{
tag
=
0
;
do
{
/* We silently ignore an overflow in the tag value. It is
not worth checking for it. */
tag
<<=
7
;
c
=
read_byte
(
reader
);
if
(
c
==
-1
)
return
eof_or_error
(
reader
,
ti
,
1
);
if
(
ti
->
nhdr
>=
DIM
(
ti
->
buf
))
{
ti
->
err_string
=
"tag+length header too large"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
tag
|=
c
&
0x7f
;
}
while
(
c
&
0x80
);
}
ti
->
tag
=
tag
;
/* Get the length */
c
=
read_byte
(
reader
);
if
(
c
==
-1
)
return
eof_or_error
(
reader
,
ti
,
1
);
if
(
ti
->
nhdr
>=
DIM
(
ti
->
buf
))
{
ti
->
err_string
=
"tag+length header too large"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
if
(
!
(
c
&
0x80
)
)
ti
->
length
=
c
;
else
if
(
c
==
0x80
)
{
ti
->
ndef
=
1
;
ti
->
non_der
=
1
;
}
else
if
(
c
==
0xff
)
{
ti
->
err_string
=
"forbidden length value"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
else
{
unsigned
long
len
=
0
;
int
count
=
c
&
0x7f
;
if
(
count
>
sizeof
(
len
)
||
count
>
sizeof
(
size_t
))
return
gpg_error
(
GPG_ERR_BAD_BER
);
for
(;
count
;
count
--
)
{
len
<<=
8
;
c
=
read_byte
(
reader
);
if
(
c
==
-1
)
return
eof_or_error
(
reader
,
ti
,
1
);
if
(
ti
->
nhdr
>=
DIM
(
ti
->
buf
))
{
ti
->
err_string
=
"tag+length header too large"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
len
|=
c
&
0xff
;
}
ti
->
length
=
len
;
}
/* Without this kludge some example certs can't be parsed */
if
(
ti
->
class
==
CLASS_UNIVERSAL
&&
!
ti
->
tag
)
ti
->
length
=
0
;
return
0
;
}
/*
Parse the buffer at the address BUFFER which of SIZE and return
the tag and the length part from the TLV triplet. Update BUFFER
and SIZE on success. */
gpg_error_t
_ksba_ber_parse_tl
(
unsigned
char
const
**
buffer
,
size_t
*
size
,
struct
tag_info
*
ti
)
{
int
c
;
unsigned
long
tag
;
const
unsigned
char
*
buf
=
*
buffer
;
size_t
length
=
*
size
;
ti
->
length
=
0
;
ti
->
ndef
=
0
;
ti
->
nhdr
=
0
;
ti
->
err_string
=
NULL
;
ti
->
non_der
=
0
;
/* Get the tag */
if
(
!
length
)
return
premature_eof
(
ti
);
c
=
*
buf
++
;
length
--
;
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
ti
->
class
=
(
c
&
0xc0
)
>>
6
;
ti
->
is_constructed
=
!!
(
c
&
0x20
);
tag
=
c
&
0x1f
;
if
(
tag
==
0x1f
)
{
tag
=
0
;
do
{
/* We silently ignore an overflow in the tag value. It is
not worth checking for it. */
tag
<<=
7
;
if
(
!
length
)
return
premature_eof
(
ti
);
c
=
*
buf
++
;
length
--
;
if
(
ti
->
nhdr
>=
DIM
(
ti
->
buf
))
{
ti
->
err_string
=
"tag+length header too large"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
tag
|=
c
&
0x7f
;
}
while
(
c
&
0x80
);
}
ti
->
tag
=
tag
;
/* Get the length */
if
(
!
length
)
return
premature_eof
(
ti
);
c
=
*
buf
++
;
length
--
;
if
(
ti
->
nhdr
>=
DIM
(
ti
->
buf
))
{
ti
->
err_string
=
"tag+length header too large"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
if
(
!
(
c
&
0x80
)
)
ti
->
length
=
c
;
else
if
(
c
==
0x80
)
{
ti
->
ndef
=
1
;
ti
->
non_der
=
1
;
}
else
if
(
c
==
0xff
)
{
ti
->
err_string
=
"forbidden length value"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
else
{
unsigned
long
len
=
0
;
int
count
=
c
&
0x7f
;
if
(
count
>
sizeof
(
len
)
||
count
>
sizeof
(
size_t
))
return
gpg_error
(
GPG_ERR_BAD_BER
);
for
(;
count
;
count
--
)
{
len
<<=
8
;
if
(
!
length
)
return
premature_eof
(
ti
);
c
=
*
buf
++
;
length
--
;
if
(
ti
->
nhdr
>=
DIM
(
ti
->
buf
))
{
ti
->
err_string
=
"tag+length header too large"
;
return
gpg_error
(
GPG_ERR_BAD_BER
);
}
ti
->
buf
[
ti
->
nhdr
++
]
=
c
;
len
|=
c
&
0xff
;
}
ti
->
length
=
len
;
}
/* Without this kludge some example certs can't be parsed */
if
(
ti
->
class
==
CLASS_UNIVERSAL
&&
!
ti
->
tag
)
ti
->
length
=
0
;
*
buffer
=
buf
;
*
size
=
length
;
return
0
;
}
/* Write TAG of CLASS to WRITER. constructed is a flag telling
whether the value is a constructed one. length gives the length of
the value, if it is 0 undefinite length is assumed. length is
ignored for the NULL tag. */
gpg_error_t
_ksba_ber_write_tl
(
ksba_writer_t
writer
,
unsigned
long
tag
,
enum
tag_class
class
,
int
constructed
,
unsigned
long
length
)
{
unsigned
char
buf
[
50
];
int
buflen
=
0
;
if
(
tag
<
0x1f
)
{
*
buf
=
(
class
<<
6
)
|
tag
;
if
(
constructed
)
*
buf
|=
0x20
;
buflen
++
;
}
else
{
return
gpg_error
(
GPG_ERR_NOT_IMPLEMENTED
);
}
if
(
!
tag
&&
!
class
)
buf
[
buflen
++
]
=
0
;
/* end tag */
else
if
(
tag
==
TYPE_NULL
&&
!
class
)
buf
[
buflen
++
]
=
0
;
/* NULL tag */
else
if
(
!
length
)
buf
[
buflen
++
]
=
0x80
;
/* indefinite length */
else
if
(
length
<
128
)
buf
[
buflen
++
]
=
length
;
else
{
int
i
;
/* fixme: if we know the sizeof an ulong we could support larger
objects - however this is pretty ridiculous */
i
=
(
length
<=
0xff
?
1
:
length
<=
0xffff
?
2
:
length
<=
0xffffff
?
3
:
4
);
buf
[
buflen
++
]
=
(
0x80
|
i
);
if
(
i
>
3
)
buf
[
buflen
++
]
=
length
>>
24
;
if
(
i
>
2
)
buf
[
buflen
++
]
=
length
>>
16
;
if
(
i
>
1
)
buf
[
buflen
++
]
=
length
>>
8
;
buf
[
buflen
++
]
=
length
;
}
return
ksba_writer_write
(
writer
,
buf
,
buflen
);
}
/* Encode TAG of CLASS in BUFFER. CONSTRUCTED is a flag telling
whether the value is a constructed one. LENGTH gives the length of
the value, if it is 0 undefinite length is assumed. LENGTH is
ignored for the NULL tag. It is assumed that the provide buffer is
large enough for storing the result - this is usually achieved by
using _ksba_ber_count_tl() in advance. Returns 0 in case of an
error or the length of the encoding.*/
size_t
_ksba_ber_encode_tl
(
unsigned
char
*
buffer
,
unsigned
long
tag
,
enum
tag_class
class
,
int
constructed
,
unsigned
long
length
)
{
unsigned
char
*
buf
=
buffer
;
if
(
tag
<
0x1f
)
{
*
buf
=
(
class
<<
6
)
|
tag
;
if
(
constructed
)
*
buf
|=
0x20
;
buf
++
;
}
else
{
return
0
;
/*Not implemented*/
}
if
(
!
tag
&&
!
class
)
*
buf
++
=
0
;
/* end tag */
else
if
(
tag
==
TYPE_NULL
&&
!
class
)
*
buf
++
=
0
;
/* NULL tag */
else
if
(
!
length
)
*
buf
++
=
0x80
;
/* indefinite length */
else
if
(
length
<
128
)
*
buf
++
=
length
;
else
{
int
i
;
/* fixme: if we know the sizeof an ulong we could support larger
objetcs - however this is pretty ridiculous */
i
=
(
length
<=
0xff
?
1
:
length
<=
0xffff
?
2
:
length
<=
0xffffff
?
3
:
4
);
*
buf
++
=
(
0x80
|
i
);
if
(
i
>
3
)
*
buf
++
=
length
>>
24
;
if
(
i
>
2
)
*
buf
++
=
length
>>
16
;
if
(
i
>
1
)
*
buf
++
=
length
>>
8
;
*
buf
++
=
length
;
}
return
buf
-
buffer
;
}
/* Calculate the length of the TL needed to encode a TAG of CLASS.
CONSTRUCTED is a flag telling whether the value is a constructed
one. LENGTH gives the length of the value; if it is 0 an
indefinite length is assumed. LENGTH is ignored for the NULL
tag. */
size_t
_ksba_ber_count_tl
(
unsigned
long
tag
,
enum
tag_class
class
,
int
constructed
,
unsigned
long
length
)
{
int
buflen
=
0
;
(
void
)
constructed
;
/* Not used, but passed for uniformity of such calls. */
if
(
tag
<
0x1f
)
{
buflen
++
;
}
else
{
buflen
++
;
/* assume one and let the actual write function bail out */
}
if
(
!
tag
&&
!
class
)
buflen
++
;
/* end tag */
else
if
(
tag
==
TYPE_NULL
&&
!
class
)
buflen
++
;
/* NULL tag */
else
if
(
!
length
)
buflen
++
;
/* indefinite length */
else
if
(
length
<
128
)
buflen
++
;
else
{
int
i
;
/* fixme: if we know the sizeof an ulong we could support larger
objetcs - however this is pretty ridiculous */
i
=
(
length
<=
0xff
?
1
:
length
<=
0xffff
?
2
:
length
<=
0xffffff
?
3
:
4
);
buflen
++
;
if
(
i
>
3
)
buflen
++
;
if
(
i
>
2
)
buflen
++
;
if
(
i
>
1
)
buflen
++
;
buflen
++
;
}
return
buflen
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Dec 23, 5:13 PM (1 h, 38 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
f7/28/e0004d792c7c462ed00548309efa
Attached To
rK libksba
Event Timeline
Log In to Comment