iPXE
asn1.c File Reference

ASN.1 encoding. More...

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <ipxe/tables.h>
#include <ipxe/image.h>
#include <ipxe/crypto.h>
#include <ipxe/asn1.h>

Go to the source code of this file.

Macros

#define EINVAL_ASN1_EMPTY   __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
#define EINFO_EINVAL_ASN1_EMPTY   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
#define EINVAL_ASN1_LEN_LEN   __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
#define EINFO_EINVAL_ASN1_LEN_LEN   __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
#define EINVAL_ASN1_LEN   __einfo_error ( EINFO_EINVAL_ASN1_LEN )
#define EINFO_EINVAL_ASN1_LEN   __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
#define EINVAL_ASN1_BOOLEAN   __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
#define EINFO_EINVAL_ASN1_BOOLEAN   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
#define EINVAL_ASN1_INTEGER   __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
#define EINFO_EINVAL_ASN1_INTEGER   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
#define EINVAL_ASN1_TIME   __einfo_error ( EINFO_EINVAL_ASN1_TIME )
#define EINFO_EINVAL_ASN1_TIME   __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )
#define EINVAL_ASN1_ALGORITHM   __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
#define EINFO_EINVAL_ASN1_ALGORITHM   __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
#define EINVAL_BIT_STRING   __einfo_error ( EINFO_EINVAL_BIT_STRING )
#define EINFO_EINVAL_BIT_STRING   __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )
#define ENOTSUP_ALGORITHM   __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
#define EINFO_ENOTSUP_ALGORITHM   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
#define ENOTTY_ALGORITHM   __einfo_error ( EINFO_ENOTTY_ALGORITHM )
#define EINFO_ENOTTY_ALGORITHM   __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static int asn1_start (struct asn1_cursor *cursor, unsigned int type)
 Start parsing ASN.1 object.
int asn1_enter (struct asn1_cursor *cursor, unsigned int type)
 Enter ASN.1 object.
int asn1_skip_if_exists (struct asn1_cursor *cursor, unsigned int type)
 Skip ASN.1 object if present.
int asn1_skip (struct asn1_cursor *cursor, unsigned int type)
 Skip ASN.1 object.
int asn1_shrink (struct asn1_cursor *cursor, unsigned int type)
 Shrink ASN.1 cursor to fit object.
int asn1_enter_any (struct asn1_cursor *cursor)
 Enter ASN.1 object of any type.
int asn1_skip_any (struct asn1_cursor *cursor)
 Skip ASN.1 object of any type.
int asn1_shrink_any (struct asn1_cursor *cursor)
 Shrink ASN.1 object of any type.
int asn1_enter_bits (struct asn1_cursor *cursor, unsigned int *unused)
 Enter ASN.1 bit string.
int asn1_enter_unsigned (struct asn1_cursor *cursor)
 Enter ASN.1 unsigned integer.
int asn1_boolean (const struct asn1_cursor *cursor)
 Parse value of ASN.1 boolean.
int asn1_integer (const struct asn1_cursor *cursor, int *value)
 Parse value of ASN.1 integer.
int asn1_compare (const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
 Compare two ASN.1 objects.
static struct asn1_algorithmasn1_find_algorithm (const struct asn1_cursor *cursor)
 Identify ASN.1 algorithm by OID.
int asn1_algorithm (const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm, struct asn1_cursor *params)
 Parse ASN.1 OID-identified algorithm.
int asn1_pubkey_algorithm (const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
 Parse ASN.1 OID-identified public-key algorithm.
int asn1_digest_algorithm (const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
 Parse ASN.1 OID-identified digest algorithm.
int asn1_cipher_algorithm (const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm, struct asn1_cursor *params)
 Parse ASN.1 OID-identified cipher algorithm.
int asn1_signature_algorithm (const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
 Parse ASN.1 OID-identified signature algorithm.
int asn1_curve_algorithm (const struct asn1_cursor *cursor, struct asn1_algorithm *wrapper, struct asn1_algorithm **algorithm)
 Parse ASN.1 OID-identified elliptic curve algorithm.
int asn1_check_algorithm (const struct asn1_cursor *cursor, struct asn1_algorithm *expected, struct asn1_cursor *params)
 Check ASN.1 OID-identified algorithm.
int asn1_parse_cbc (struct asn1_algorithm *algorithm, struct asn1_cursor *params)
 Parse ASN.1 CBC cipher parameters.
int asn1_parse_gcm (struct asn1_algorithm *algorithm __unused, struct asn1_cursor *params)
 Parse ASN.1 GCM cipher parameters.
int asn1_generalized_time (const struct asn1_cursor *cursor, time_t *time)
 Parse ASN.1 GeneralizedTime.
static size_t asn1_header (struct asn1_builder_header *header, unsigned int type, size_t len)
 Construct ASN.1 header.
int asn1_grow (struct asn1_builder *builder, size_t extra)
 Grow ASN.1 builder.
int asn1_prepend_raw (struct asn1_builder *builder, const void *data, size_t len)
 Prepend raw data to ASN.1 builder.
int asn1_prepend (struct asn1_builder *builder, unsigned int type, const void *data, size_t len)
 Prepend data to ASN.1 builder.
int asn1_wrap (struct asn1_builder *builder, unsigned int type)
 Wrap ASN.1 builder.
int image_asn1 (struct image *image, size_t offset, struct asn1_cursor **cursor)
 Extract ASN.1 object from image.
 REQUIRING_SYMBOL (image_asn1)
 REQUIRE_OBJECT (config_asn1)

Detailed Description

ASN.1 encoding.

The ASN.1 parsing helper functions are designed to be safe to use on untrusted input, including malformed input. Any parsing error will cause the function to invalidate the cursor by setting its length field to zero before returning.

All parsing helper functions will strictly respect the cursor's bounds for all purposes (including for determining the tag type and the tag length). An invalidated cursor (or any cursor that happens to naturally end up with a zero length, e.g. by skipping the only existent object) may therefore safely be passed in to any parsing helper function.

A consequence of this design is that it is not necessary to check the return status from all parsing helper functions in a sequence, only to check the return status from the last. The standard C comma operator may safely be used to connect a sequence of ASN.1 parsing operations. For example:

if ( ( rc = ( asn1_enter ( cursor, ASN1_SEQUENCE ),
asn1_skip ( cursor, ASN1_INTEGER ),
asn1_enter ( cursor, ASN1_SEQUENCE ) ) ) != 0 ) {
return rc;
}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:239
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:301
#define ASN1_INTEGER
ASN.1 integer.
Definition asn1.h:63
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:90

or equivalently, just:

asn1_skip ( cursor, ASN1_INTEGER );
if ( ( rc = asn1_enter ( cursor, ASN1_SEQUENCE ) ) != 0 )
return rc;

The caller may not need to check the return status from the parsing helper functions at all. For example, a caller that is trying to extract a fixed-length octet string from within a deeply nested ASN.1 structure may simply check that the resulting cursor length is correct (which it would have to check anyway). Since any error will produce a zero-length cursor, this check would also suffice to catch any parsing errors.

The cursor navigation functions such as asn1_enter() and asn1_skip() will validate the type and length bytes (which they consume themselves), but will not otherwise validate the contents of the cursor. Callers must perform their own validation after navigating to the expected data structure (e.g. by checking that the resulting length is correct), or use the higher-level helpers such as asn1_boolean() and asn1_integer() that validate and extract the semantic contents of cursors.

The type ASN1_ANY may be used as a wildcard type to enter or skip an object of any type.

The function asn1_skip_if_exists() may be useful when parsing objects where an encountered type is not knowable in advance (e.g. for sequences containing optional elements). If the potential type is not found, then asn1_skip_if_exists() will return an error but will not invalidate the cursor (since a missing optional object is not a parsing error).

The function asn1_type() may be used to determine the type of an unknown object. Calling asn1_type() on an invalidated cursor will return ASN1_END (and the cursor will remain invalidated).

Definition in file asn1.c.

Macro Definition Documentation

◆ EINVAL_ASN1_EMPTY

#define EINVAL_ASN1_EMPTY   __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )

Definition at line 116 of file asn1.c.

116#define EINVAL_ASN1_EMPTY \
117 __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )

Referenced by asn1_start().

◆ EINFO_EINVAL_ASN1_EMPTY

#define EINFO_EINVAL_ASN1_EMPTY   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )

Definition at line 118 of file asn1.c.

118#define EINFO_EINVAL_ASN1_EMPTY \
119 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )

◆ EINVAL_ASN1_LEN_LEN

#define EINVAL_ASN1_LEN_LEN   __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )

Definition at line 120 of file asn1.c.

120#define EINVAL_ASN1_LEN_LEN \
121 __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )

Referenced by asn1_start().

◆ EINFO_EINVAL_ASN1_LEN_LEN

#define EINFO_EINVAL_ASN1_LEN_LEN   __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )

Definition at line 122 of file asn1.c.

122#define EINFO_EINVAL_ASN1_LEN_LEN \
123 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )

◆ EINVAL_ASN1_LEN

#define EINVAL_ASN1_LEN   __einfo_error ( EINFO_EINVAL_ASN1_LEN )

Definition at line 124 of file asn1.c.

124#define EINVAL_ASN1_LEN \
125 __einfo_error ( EINFO_EINVAL_ASN1_LEN )

Referenced by asn1_start().

◆ EINFO_EINVAL_ASN1_LEN

#define EINFO_EINVAL_ASN1_LEN   __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )

Definition at line 126 of file asn1.c.

126#define EINFO_EINVAL_ASN1_LEN \
127 __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )

◆ EINVAL_ASN1_BOOLEAN

#define EINVAL_ASN1_BOOLEAN   __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )

Definition at line 128 of file asn1.c.

128#define EINVAL_ASN1_BOOLEAN \
129 __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )

Referenced by asn1_boolean().

◆ EINFO_EINVAL_ASN1_BOOLEAN

#define EINFO_EINVAL_ASN1_BOOLEAN   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )

Definition at line 130 of file asn1.c.

130#define EINFO_EINVAL_ASN1_BOOLEAN \
131 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )

◆ EINVAL_ASN1_INTEGER

#define EINVAL_ASN1_INTEGER   __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )

Definition at line 132 of file asn1.c.

132#define EINVAL_ASN1_INTEGER \
133 __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )

Referenced by asn1_integer().

◆ EINFO_EINVAL_ASN1_INTEGER

#define EINFO_EINVAL_ASN1_INTEGER   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )

Definition at line 134 of file asn1.c.

134#define EINFO_EINVAL_ASN1_INTEGER \
135 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )

◆ EINVAL_ASN1_TIME

#define EINVAL_ASN1_TIME   __einfo_error ( EINFO_EINVAL_ASN1_TIME )

Definition at line 136 of file asn1.c.

136#define EINVAL_ASN1_TIME \
137 __einfo_error ( EINFO_EINVAL_ASN1_TIME )

Referenced by asn1_generalized_time().

◆ EINFO_EINVAL_ASN1_TIME

#define EINFO_EINVAL_ASN1_TIME   __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )

Definition at line 138 of file asn1.c.

138#define EINFO_EINVAL_ASN1_TIME \
139 __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )

◆ EINVAL_ASN1_ALGORITHM

#define EINVAL_ASN1_ALGORITHM   __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )

Definition at line 140 of file asn1.c.

140#define EINVAL_ASN1_ALGORITHM \
141 __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )

Referenced by asn1_algorithm().

◆ EINFO_EINVAL_ASN1_ALGORITHM

#define EINFO_EINVAL_ASN1_ALGORITHM   __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )

Definition at line 142 of file asn1.c.

142#define EINFO_EINVAL_ASN1_ALGORITHM \
143 __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )

◆ EINVAL_BIT_STRING

#define EINVAL_BIT_STRING   __einfo_error ( EINFO_EINVAL_BIT_STRING )

Definition at line 144 of file asn1.c.

144#define EINVAL_BIT_STRING \
145 __einfo_error ( EINFO_EINVAL_BIT_STRING )

Referenced by asn1_enter_bits().

◆ EINFO_EINVAL_BIT_STRING

#define EINFO_EINVAL_BIT_STRING   __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )

Definition at line 146 of file asn1.c.

146#define EINFO_EINVAL_BIT_STRING \
147 __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )

◆ ENOTSUP_ALGORITHM

#define ENOTSUP_ALGORITHM   __einfo_error ( EINFO_ENOTSUP_ALGORITHM )

Definition at line 148 of file asn1.c.

148#define ENOTSUP_ALGORITHM \
149 __einfo_error ( EINFO_ENOTSUP_ALGORITHM )

Referenced by asn1_algorithm(), and asn1_curve_algorithm().

◆ EINFO_ENOTSUP_ALGORITHM

#define EINFO_ENOTSUP_ALGORITHM   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )

Definition at line 150 of file asn1.c.

150#define EINFO_ENOTSUP_ALGORITHM \
151 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )

◆ ENOTTY_ALGORITHM

#define ENOTTY_ALGORITHM   __einfo_error ( EINFO_ENOTTY_ALGORITHM )

Definition at line 152 of file asn1.c.

152#define ENOTTY_ALGORITHM \
153 __einfo_error ( EINFO_ENOTTY_ALGORITHM )

Referenced by asn1_check_algorithm(), asn1_cipher_algorithm(), asn1_curve_algorithm(), asn1_digest_algorithm(), asn1_pubkey_algorithm(), and asn1_signature_algorithm().

◆ EINFO_ENOTTY_ALGORITHM

#define EINFO_ENOTTY_ALGORITHM   __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )

Definition at line 154 of file asn1.c.

154#define EINFO_ENOTTY_ALGORITHM \
155 __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ asn1_start()

int asn1_start ( struct asn1_cursor * cursor,
unsigned int type )
static

Start parsing ASN.1 object.

Parameters
cursorASN.1 object cursor
typeExpected type, or ASN1_ANY
Return values
lenLength of object body, or negative error

The object cursor will be updated to point to the start of the object body (i.e. the first byte following the length byte(s)), and the length of the object body (i.e. the number of bytes until the following object tag, if any) is returned.

If the expected type is not found, the object cursor will not be modified. If any other error occurs, the object cursor will be invalidated.

Definition at line 173 of file asn1.c.

173 {
174 unsigned int len_len;
175 unsigned int len;
176
177 /* Sanity check */
178 if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
179 if ( cursor->len )
180 DBGC ( cursor, "ASN1 %p too short\n", cursor );
181 asn1_invalidate_cursor ( cursor );
182 return -EINVAL_ASN1_EMPTY;
183 }
184
185 /* Check the tag byte */
186 if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
187 DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
188 cursor, type, *( ( uint8_t * ) cursor->data ) );
189 return -ENXIO;
190 }
191 cursor->data++;
192 cursor->len--;
193
194 /* Extract length of the length field and sanity check */
195 len_len = *( ( uint8_t * ) cursor->data );
196 if ( len_len & 0x80 ) {
197 len_len = ( len_len & 0x7f );
198 cursor->data++;
199 cursor->len--;
200 } else {
201 len_len = 1;
202 }
203 if ( cursor->len < len_len ) {
204 DBGC ( cursor, "ASN1 %p bad length field length %d (max "
205 "%zd)\n", cursor, len_len, cursor->len );
206 asn1_invalidate_cursor ( cursor );
207 return -EINVAL_ASN1_LEN_LEN;
208 }
209
210 /* Extract the length and sanity check */
211 for ( len = 0 ; len_len ; len_len-- ) {
212 len <<= 8;
213 len |= *( ( uint8_t * ) cursor->data );
214 cursor->data++;
215 cursor->len--;
216 }
217 if ( cursor->len < len ) {
218 DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
219 cursor, len, cursor->len );
220 asn1_invalidate_cursor ( cursor );
221 return -EINVAL_ASN1_LEN;
222 }
223
224 return len;
225}
unsigned char uint8_t
Definition stdint.h:10
#define EINVAL_ASN1_LEN_LEN
Definition asn1.c:120
#define EINVAL_ASN1_EMPTY
Definition asn1.c:116
#define EINVAL_ASN1_LEN
Definition asn1.c:124
#define ASN1_ANY
ASN.1 "any tag" magic value.
Definition asn1.h:102
static void asn1_invalidate_cursor(struct asn1_cursor *cursor)
Invalidate ASN.1 object cursor.
Definition asn1.h:475
static unsigned int asn1_type(const struct asn1_cursor *cursor)
Extract ASN.1 type.
Definition asn1.h:486
ring len
Length.
Definition dwmac.h:226
uint32_t type
Operating system type.
Definition ena.h:1
#define DBGC(...)
Definition compiler.h:530
#define ENXIO
No such device or address.
Definition errno.h:600
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25

References ASN1_ANY, asn1_invalidate_cursor(), asn1_type(), asn1_cursor::data, DBGC, EINVAL_ASN1_EMPTY, EINVAL_ASN1_LEN, EINVAL_ASN1_LEN_LEN, ENXIO, asn1_cursor::len, len, and type.

Referenced by asn1_enter(), asn1_shrink(), and asn1_skip_if_exists().

◆ asn1_enter()

int asn1_enter ( struct asn1_cursor * cursor,
unsigned int type )

Enter ASN.1 object.

Parameters
cursorASN.1 object cursor
typeExpected type, or ASN1_ANY
Return values
rcReturn status code

The object cursor will be updated to point to the body of the current ASN.1 object.

If any error occurs, the object cursor will be invalidated.

Definition at line 239 of file asn1.c.

239 {
240 int len;
241
242 /* Parse current object */
243 len = asn1_start ( cursor, type );
244 if ( len < 0 ) {
245 asn1_invalidate_cursor ( cursor );
246 return len;
247 }
248
249 /* Update cursor */
250 if ( ( ( size_t ) len ) <= cursor->len )
251 cursor->len = len;
252
253 DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
254 cursor, type, len );
255 return 0;
256}
static int asn1_start(struct asn1_cursor *cursor, unsigned int type)
Start parsing ASN.1 object.
Definition asn1.c:173

References asn1_invalidate_cursor(), asn1_start(), DBGC, asn1_cursor::len, len, and type.

Referenced by asn1_algorithm(), asn1_boolean(), asn1_curve_algorithm(), asn1_enter_any(), asn1_enter_bits(), asn1_enter_unsigned(), asn1_generalized_time(), asn1_integer(), asn1_parse_cbc(), asn1_parse_gcm(), cms_parse(), cms_parse_certificates(), cms_parse_content_type(), cms_parse_encrypted(), cms_parse_enveloped(), cms_parse_identifier(), cms_parse_mac(), cms_parse_participant(), cms_parse_participants(), cms_parse_signed(), cms_parse_value(), ecdsa_parse_key(), ecdsa_verify(), ocsp_compare_responder_key_hash(), ocsp_parse_basic_response(), ocsp_parse_cert_id(), ocsp_parse_certs(), ocsp_parse_response(), ocsp_parse_response_bytes(), ocsp_parse_response_status(), ocsp_parse_response_type(), ocsp_parse_responses(), ocsp_parse_tbs_response_data(), ocsp_request(), rsa_parse_mod_exp(), validator_append(), x509_parse(), x509_parse_access_description(), x509_parse_authority_info_access(), x509_parse_basic_constraints(), x509_parse_common_name(), x509_parse_extended_key_usage(), x509_parse_extension(), x509_parse_extensions(), x509_parse_key_purpose(), x509_parse_ocsp(), x509_parse_public_key(), x509_parse_subject_alt_name(), x509_parse_tbscertificate(), x509_parse_validity(), and x509_parse_version().

◆ asn1_skip_if_exists()

int asn1_skip_if_exists ( struct asn1_cursor * cursor,
unsigned int type )

Skip ASN.1 object if present.

Parameters
cursorASN.1 object cursor
typeExpected type, or ASN1_ANY
Return values
rcReturn status code

The object cursor will be updated to point to the next ASN.1 object.

If the expected type is not found, the object cursor will not be modified. If any other error occurs, the object cursor will be invalidated.

Definition at line 272 of file asn1.c.

272 {
273 int len;
274
275 /* Parse current object */
276 len = asn1_start ( cursor, type );
277 if ( len < 0 )
278 return len;
279
280 /* Update cursor */
281 cursor->data += len;
282 cursor->len -= len;
283
284 DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
285 cursor, type, len );
286 return 0;
287}

References asn1_start(), asn1_cursor::data, DBGC, asn1_cursor::len, len, and type.

Referenced by asn1_skip(), cms_parse_enveloped(), cms_parse_participant(), cms_parse_signed(), and ocsp_parse_tbs_response_data().

◆ asn1_skip()

int asn1_skip ( struct asn1_cursor * cursor,
unsigned int type )

Skip ASN.1 object.

Parameters
cursorASN.1 object cursor
typeExpected type, or ASN1_ANY
Return values
rcReturn status code

The object cursor will be updated to point to the next ASN.1 object.

If any error occurs, the object cursor will be invalidated.

Definition at line 301 of file asn1.c.

301 {
302 int rc;
303
304 if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
305 asn1_invalidate_cursor ( cursor );
306 return rc;
307 }
308
309 return 0;
310}
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition asn1.c:272

References asn1_invalidate_cursor(), asn1_skip_if_exists(), rc, and type.

Referenced by asn1_skip_any(), cms_parse_encrypted(), cms_parse_enveloped(), cms_parse_participant(), cms_parse_signed(), der_image_probe(), ecdsa_parse_key(), ocsp_parse_cert_id(), ocsp_request(), and rsa_parse_mod_exp().

◆ asn1_shrink()

int asn1_shrink ( struct asn1_cursor * cursor,
unsigned int type )

Shrink ASN.1 cursor to fit object.

Parameters
cursorASN.1 object cursor
typeExpected type, or ASN1_ANY
Return values
rcReturn status code

The object cursor will be shrunk to contain only the current ASN.1 object.

If any error occurs, the object cursor will be invalidated.

Definition at line 324 of file asn1.c.

324 {
325 struct asn1_cursor temp;
326 const void *end;
327 int len;
328
329 /* Find end of object */
330 memcpy ( &temp, cursor, sizeof ( temp ) );
331 len = asn1_start ( &temp, type );
332 if ( len < 0 ) {
333 asn1_invalidate_cursor ( cursor );
334 return len;
335 }
336 end = ( temp.data + len );
337
338 /* Shrink original cursor to contain only its first object */
339 cursor->len = ( end - cursor->data );
340
341 return 0;
342}
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint32_t end
Ending offset.
Definition netvsc.h:7
An ASN.1 object cursor.
Definition asn1.h:21

References asn1_invalidate_cursor(), asn1_start(), asn1_cursor::data, end, asn1_cursor::len, len, memcpy(), and type.

Referenced by asn1_shrink_any(), cms_parse_identifier(), ocsp_parse_cert_id(), x509_parse_issuer(), and x509_parse_serial().

◆ asn1_enter_any()

int asn1_enter_any ( struct asn1_cursor * cursor)

Enter ASN.1 object of any type.

Parameters
cursorASN.1 object cursor
Return values
rcReturn status code

Definition at line 350 of file asn1.c.

350 {
351 return asn1_enter ( cursor, ASN1_ANY );
352}

References ASN1_ANY, and asn1_enter().

Referenced by ecdsa_parse_key(), ocsp_parse_responder_id(), x509_check_alt_name(), and x509_parse_common_name().

◆ asn1_skip_any()

◆ asn1_shrink_any()

int asn1_shrink_any ( struct asn1_cursor * cursor)

Shrink ASN.1 object of any type.

Parameters
cursorASN.1 object cursor
Return values
rcReturn status code

Definition at line 370 of file asn1.c.

370 {
371 return asn1_shrink ( cursor, ASN1_ANY );
372}
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition asn1.c:324

References ASN1_ANY, and asn1_shrink().

Referenced by cms_message(), der_asn1(), ocsp_parse_tbs_response_data(), x509_certificate(), x509_parse_public_key(), x509_parse_subject(), and x509_parse_tbscertificate().

◆ asn1_enter_bits()

int asn1_enter_bits ( struct asn1_cursor * cursor,
unsigned int * unused )

Enter ASN.1 bit string.

Parameters
cursorASN.1 cursor
unusedUnused bits to fill in (or NULL to require all used)
Return values
rcReturn status code

Definition at line 381 of file asn1.c.

381 {
382 const struct {
384 uint8_t data[0];
385 } __attribute__ (( packed )) *bit_string;
386 const uint8_t *last;
387 unsigned int unused_bits;
388 uint8_t unused_mask;
389 int rc;
390
391 /* Enter bit string */
392 if ( ( rc = asn1_enter ( cursor, ASN1_BIT_STRING ) ) != 0 )
393 return rc;
394
395 /* Check that bit string header exists */
396 if ( cursor->len < sizeof ( *bit_string ) ) {
397 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
398 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
399 asn1_invalidate_cursor ( cursor );
400 return -EINVAL_BIT_STRING;
401 }
402 bit_string = cursor->data;
403 cursor->data = &bit_string->data;
404 cursor->len -= offsetof ( typeof ( *bit_string ), data );
405 unused_bits = bit_string->unused;
406
407 /* Check validity of unused bits */
408 unused_mask = ( 0xff >> ( 8 - unused_bits ) );
409 last = ( cursor->data + cursor->len - 1 );
410 if ( ( unused_bits >= 8 ) ||
411 ( ( unused_bits > 0 ) && ( cursor->len == 0 ) ) ||
412 ( ( *last & unused_mask ) != 0 ) ) {
413 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
414 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
415 asn1_invalidate_cursor ( cursor );
416 return -EINVAL_BIT_STRING;
417 }
418
419 /* Record or check number of unused bits, as applicable */
420 if ( unused ) {
421 *unused = unused_bits;
422 } else if ( unused_bits ) {
423 DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
424 cursor );
425 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
426 asn1_invalidate_cursor ( cursor );
427 return -EINVAL_BIT_STRING;
428 }
429
430 return 0;
431}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
#define EINVAL_BIT_STRING
Definition asn1.c:144
#define ASN1_BIT_STRING
ASN.1 bit string.
Definition asn1.h:66
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define DBGC_HDA(...)
Definition compiler.h:531
#define __attribute__(x)
Definition compiler.h:10
uint8_t unused
Unused.
Definition librm.h:5
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25

References __attribute__, ASN1_BIT_STRING, asn1_enter(), asn1_invalidate_cursor(), asn1_cursor::data, data, DBGC, DBGC_HDA, EINVAL_BIT_STRING, asn1_cursor::len, offsetof, rc, typeof(), and unused.

Referenced by ecdsa_parse_key(), ocsp_parse_basic_response(), rsa_parse_mod_exp(), x509_parse(), x509_parse_key_usage(), and x509_parse_public_key().

◆ asn1_enter_unsigned()

int asn1_enter_unsigned ( struct asn1_cursor * cursor)

Enter ASN.1 unsigned integer.

Parameters
cursorASN.1 object cursor
Return values
rcReturn status code

Definition at line 439 of file asn1.c.

439 {
440 int rc;
441
442 /* Enter integer */
443 if ( ( rc = asn1_enter ( cursor, ASN1_INTEGER ) ) != 0 )
444 return rc;
445
446 /* Skip initial positive sign byte if applicable */
447 if ( ( cursor->len > 1 ) &&
448 ( *( ( uint8_t * ) cursor->data ) == 0x00 ) ) {
449 cursor->data++;
450 cursor->len--;
451 }
452
453 return 0;
454}

References asn1_enter(), ASN1_INTEGER, asn1_cursor::data, asn1_cursor::len, and rc.

Referenced by ecdsa_parse_signature(), and rsa_parse_mod_exp().

◆ asn1_boolean()

int asn1_boolean ( const struct asn1_cursor * cursor)

Parse value of ASN.1 boolean.

Parameters
cursorASN.1 object cursor
Return values
valueValue, or negative error

Definition at line 462 of file asn1.c.

462 {
463 struct asn1_cursor contents;
464 const struct {
466 } __attribute__ (( packed )) *boolean;
467
468 /* Enter boolean */
469 memcpy ( &contents, cursor, sizeof ( contents ) );
470 asn1_enter ( &contents, ASN1_BOOLEAN );
471 if ( contents.len != sizeof ( *boolean ) )
472 return -EINVAL_ASN1_BOOLEAN;
473
474 /* Extract value */
475 boolean = contents.data;
476 return boolean->value;
477}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
#define EINVAL_ASN1_BOOLEAN
Definition asn1.c:128
#define ASN1_BOOLEAN
ASN.1 boolean.
Definition asn1.h:60

References __attribute__, ASN1_BOOLEAN, asn1_enter(), asn1_cursor::data, EINVAL_ASN1_BOOLEAN, asn1_cursor::len, memcpy(), and value.

Referenced by x509_parse_basic_constraints(), and x509_parse_extension().

◆ asn1_integer()

int asn1_integer ( const struct asn1_cursor * cursor,
int * value )

Parse value of ASN.1 integer.

Parameters
cursorASN.1 object cursor
valueValue to fill in
Return values
rcReturn status code

Definition at line 486 of file asn1.c.

486 {
487 struct asn1_cursor contents;
488 uint8_t high_byte;
489 int rc;
490
491 /* Enter integer */
492 memcpy ( &contents, cursor, sizeof ( contents ) );
493 if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
494 return rc;
495 if ( contents.len < 1 )
496 return -EINVAL_ASN1_INTEGER;
497
498 /* Initialise value according to sign byte */
499 *value = *( ( int8_t * ) contents.data );
500 contents.data++;
501 contents.len--;
502
503 /* Process value */
504 while ( contents.len ) {
505 high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
506 if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
507 DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
508 return -EINVAL_ASN1_INTEGER;
509 }
510 *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
511 contents.data++;
512 contents.len--;
513 }
514
515 return 0;
516}
signed char int8_t
Definition stdint.h:15
#define EINVAL_ASN1_INTEGER
Definition asn1.c:132

References asn1_enter(), ASN1_INTEGER, asn1_cursor::data, DBGC, EINVAL_ASN1_INTEGER, asn1_cursor::len, memcpy(), rc, and value.

Referenced by x509_parse_basic_constraints(), and x509_parse_version().

◆ asn1_compare()

int asn1_compare ( const struct asn1_cursor * cursor1,
const struct asn1_cursor * cursor2 )

Compare two ASN.1 objects.

Parameters
cursor1ASN.1 object cursor
cursor2ASN.1 object cursor
Return values
differenceDifference as returned by memcmp()

Note that invalid and empty cursors will compare as equal with each other.

Definition at line 528 of file asn1.c.

529 {
530 int difference;
531
532 difference = ( cursor2->len - cursor1->len );
533 return ( difference ? difference :
534 memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
535}
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115

References asn1_cursor::data, asn1_cursor::len, and memcmp().

Referenced by asn1_find_algorithm(), cms_parse_content_type(), ocsp_compare_responder_name(), ocsp_parse_cert_id(), ocsp_parse_response_type(), pubkey_okx(), pubkey_sign_okx(), rsa_match(), x509_check_issuer(), x509_find(), x509_find_access_method(), x509_find_extension(), x509_find_issuer_serial(), x509_find_subject(), x509_is_self_signed(), x509_parse_common_name(), and x509_parse_key_purpose().

◆ asn1_find_algorithm()

struct asn1_algorithm * asn1_find_algorithm ( const struct asn1_cursor * cursor)
static

Identify ASN.1 algorithm by OID.

Parameters
cursorASN.1 object cursor
Return values
algorithmAlgorithm, or NULL

Definition at line 545 of file asn1.c.

545 {
547
549 if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
550 return algorithm;
551 }
552
553 return NULL;
554}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:528
#define ASN1_ALGORITHMS
ASN.1 OID-identified algorithms.
Definition asn1.h:439
u16 algorithm
Authentication algorithm (Open System or Shared Key).
Definition ieee80211.h:1
An ASN.1 OID-identified algorithm.
Definition asn1.h:414
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References algorithm, ASN1_ALGORITHMS, asn1_compare(), for_each_table_entry, and NULL.

Referenced by asn1_algorithm(), and asn1_curve_algorithm().

◆ asn1_algorithm()

int asn1_algorithm ( const struct asn1_cursor * cursor,
struct asn1_algorithm ** algorithm,
struct asn1_cursor * params )

Parse ASN.1 OID-identified algorithm.

Parameters
cursorASN.1 object cursor
Return values
algorithmAlgorithm
paramsAlgorithm parameters, or NULL
rcReturn status code

Definition at line 564 of file asn1.c.

566 {
567 struct asn1_cursor contents;
568 int rc;
569
570 /* Enter algorithm */
571 memcpy ( &contents, cursor, sizeof ( contents ) );
572 asn1_enter ( &contents, ASN1_SEQUENCE );
573
574 /* Get raw parameters, if applicable */
575 if ( params ) {
576 memcpy ( params, &contents, sizeof ( *params ) );
577 asn1_skip_any ( params );
578 }
579
580 /* Enter algorithm identifier */
581 if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
582 DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
583 cursor );
584 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
585 return -EINVAL_ASN1_ALGORITHM;
586 }
587
588 /* Identify algorithm */
589 *algorithm = asn1_find_algorithm ( &contents );
590 if ( ! *algorithm ) {
591 DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
592 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
593 return -ENOTSUP_ALGORITHM;
594 }
595
596 /* Parse parameters, if applicable */
597 if ( params && (*algorithm)->parse &&
598 ( ( rc = (*algorithm)->parse ( *algorithm, params ) ) != 0 ) ) {
599 DBGC ( cursor, "ASN1 %p cannot parse %s parameters: %s\n",
600 cursor, (*algorithm)->name, strerror ( rc ) );
601 return rc;
602 }
603
604 return 0;
605}
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:360
#define ENOTSUP_ALGORITHM
Definition asn1.c:148
#define EINVAL_ASN1_ALGORITHM
Definition asn1.c:140
static struct asn1_algorithm * asn1_find_algorithm(const struct asn1_cursor *cursor)
Identify ASN.1 algorithm by OID.
Definition asn1.c:545
#define ASN1_OID
ASN.1 object identifier.
Definition asn1.h:75
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79

References algorithm, asn1_enter(), asn1_find_algorithm(), ASN1_OID, ASN1_SEQUENCE, asn1_skip_any(), asn1_cursor::data, DBGC, DBGC_HDA, EINVAL_ASN1_ALGORITHM, ENOTSUP_ALGORITHM, asn1_cursor::len, memcpy(), rc, and strerror().

◆ asn1_pubkey_algorithm()

int asn1_pubkey_algorithm ( const struct asn1_cursor * cursor,
struct asn1_algorithm ** algorithm )

Parse ASN.1 OID-identified public-key algorithm.

Parameters
cursorASN.1 object cursor
Return values
algorithmAlgorithm
rcReturn status code

Definition at line 614 of file asn1.c.

615 {
616 int rc;
617
618 /* Parse algorithm */
619 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
620 return rc;
621
622 /* Check algorithm has a public key */
623 if ( ! (*algorithm)->pubkey ) {
624 DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key "
625 "algorithm:\n", cursor, (*algorithm)->name );
626 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
627 return -ENOTTY_ALGORITHM;
628 }
629
630 return 0;
631}
#define ENOTTY_ALGORITHM
Definition asn1.c:152

References algorithm, asn1_cursor::data, DBGC, DBGC_HDA, ENOTTY_ALGORITHM, asn1_cursor::len, NULL, and rc.

Referenced by cms_parse_pubkey_algorithm(), and x509_parse_public_key().

◆ asn1_digest_algorithm()

int asn1_digest_algorithm ( const struct asn1_cursor * cursor,
struct asn1_algorithm ** algorithm )

Parse ASN.1 OID-identified digest algorithm.

Parameters
cursorASN.1 object cursor
Return values
algorithmAlgorithm
rcReturn status code

Definition at line 640 of file asn1.c.

641 {
642 int rc;
643
644 /* Parse algorithm */
645 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
646 return rc;
647
648 /* Check algorithm has a digest */
649 if ( ! (*algorithm)->digest ) {
650 DBGC ( cursor, "ASN1 %p algorithm %s is not a digest "
651 "algorithm:\n", cursor, (*algorithm)->name );
652 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
653 return -ENOTTY_ALGORITHM;
654 }
655
656 return 0;
657}

References algorithm, asn1_cursor::data, DBGC, DBGC_HDA, ENOTTY_ALGORITHM, asn1_cursor::len, NULL, and rc.

Referenced by cms_parse_digest_algorithm().

◆ asn1_cipher_algorithm()

int asn1_cipher_algorithm ( const struct asn1_cursor * cursor,
struct asn1_algorithm ** algorithm,
struct asn1_cursor * params )

Parse ASN.1 OID-identified cipher algorithm.

Parameters
cursorASN.1 object cursor
Return values
algorithmAlgorithm
paramsAlgorithm parameters, or NULL
rcReturn status code

Definition at line 667 of file asn1.c.

669 {
670 int rc;
671
672 /* Parse algorithm */
673 if ( ( rc = asn1_algorithm ( cursor, algorithm, params ) ) != 0 )
674 return rc;
675
676 /* Check algorithm has a cipher */
677 if ( ! (*algorithm)->cipher ) {
678 DBGC ( cursor, "ASN1 %p algorithm %s is not a cipher "
679 "algorithm:\n", cursor, (*algorithm)->name );
680 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
681 return -ENOTTY_ALGORITHM;
682 }
683
684 return 0;
685}

References algorithm, asn1_cursor::data, DBGC, DBGC_HDA, ENOTTY_ALGORITHM, asn1_cursor::len, and rc.

Referenced by cms_parse_cipher_algorithm().

◆ asn1_signature_algorithm()

int asn1_signature_algorithm ( const struct asn1_cursor * cursor,
struct asn1_algorithm ** algorithm )

Parse ASN.1 OID-identified signature algorithm.

Parameters
cursorASN.1 object cursor
Return values
algorithmAlgorithm
rcReturn status code

Definition at line 694 of file asn1.c.

695 {
696 int rc;
697
698 /* Parse algorithm */
699 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
700 return rc;
701
702 /* Check algorithm has a public key */
703 if ( ! (*algorithm)->pubkey ) {
704 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
705 "algorithm:\n", cursor, (*algorithm)->name );
706 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
707 return -ENOTTY_ALGORITHM;
708 }
709
710 /* Check algorithm has a digest */
711 if ( ! (*algorithm)->digest ) {
712 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
713 "algorithm:\n", cursor, (*algorithm)->name );
714 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
715 return -ENOTTY_ALGORITHM;
716 }
717
718 return 0;
719}

References algorithm, asn1_cursor::data, DBGC, DBGC_HDA, ENOTTY_ALGORITHM, asn1_cursor::len, NULL, and rc.

Referenced by ocsp_parse_basic_response(), x509_parse(), and x509_parse_tbscertificate().

◆ asn1_curve_algorithm()

int asn1_curve_algorithm ( const struct asn1_cursor * cursor,
struct asn1_algorithm * wrapper,
struct asn1_algorithm ** algorithm )

Parse ASN.1 OID-identified elliptic curve algorithm.

Parameters
cursorASN.1 object cursor
wrapperOptional wrapper algorithm, or NULL
Return values
algorithmAlgorithm
rcReturn status code

Definition at line 729 of file asn1.c.

731 {
732 struct asn1_cursor curve;
733
734 /* Elliptic curves are identified as either:
735 *
736 * - a wrapper algorithm "id-ecPublicKey" with the actual
737 * curve specified in the algorithm parameters, or
738 *
739 * - a standalone object identifier for the curve
740 */
741 if ( ( wrapper == NULL ) ||
742 ( asn1_check_algorithm ( cursor, wrapper, &curve ) != 0 ) ) {
743 memcpy ( &curve, cursor, sizeof ( curve ) );
744 }
745
746 /* Identify curve */
747 asn1_enter ( &curve, ASN1_OID );
748 *algorithm = asn1_find_algorithm ( &curve );
749 if ( ! *algorithm ) {
750 DBGC ( cursor, "ASN1 %p unrecognised EC algorithm:\n",
751 cursor );
752 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
753 return -ENOTSUP_ALGORITHM;
754 }
755
756 /* Check algorithm has an elliptic curve */
757 if ( ! (*algorithm)->curve ) {
758 DBGC ( cursor, "ASN1 %p algorithm %s is not an elliptic curve "
759 "algorithm:\n", cursor, (*algorithm)->name );
760 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
761 return -ENOTTY_ALGORITHM;
762 }
763
764 return 0;
765}
int asn1_check_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm *expected, struct asn1_cursor *params)
Check ASN.1 OID-identified algorithm.
Definition asn1.c:775

References algorithm, asn1_check_algorithm(), asn1_enter(), asn1_find_algorithm(), ASN1_OID, asn1_cursor::data, DBGC, DBGC_HDA, ENOTSUP_ALGORITHM, ENOTTY_ALGORITHM, asn1_cursor::len, memcpy(), and NULL.

Referenced by ecdsa_parse_key().

◆ asn1_check_algorithm()

int asn1_check_algorithm ( const struct asn1_cursor * cursor,
struct asn1_algorithm * expected,
struct asn1_cursor * params )

Check ASN.1 OID-identified algorithm.

Parameters
cursorASN.1 object cursor
expectedExpected algorithm
Return values
paramsAlgorithm parameters, or NULL
rcReturn status code

Definition at line 775 of file asn1.c.

777 {
778 struct asn1_algorithm *actual;
779 int rc;
780
781 /* Parse algorithm */
782 if ( ( rc = asn1_algorithm ( cursor, &actual, params ) ) != 0 )
783 return rc;
784
785 /* Check algorithm matches */
786 if ( actual != expected ) {
787 DBGC ( cursor, "ASN1 %p algorithm %s does not match %s\n",
788 cursor, actual->name, expected->name );
789 return -ENOTTY_ALGORITHM;
790 }
791
792 return 0;
793}
const char * name
Name.
Definition asn1.h:416

References DBGC, ENOTTY_ALGORITHM, asn1_algorithm::name, and rc.

Referenced by asn1_curve_algorithm(), and rsa_parse_mod_exp().

◆ asn1_parse_cbc()

int asn1_parse_cbc ( struct asn1_algorithm * algorithm,
struct asn1_cursor * params )

Parse ASN.1 CBC cipher parameters.

Parameters
algorithmAlgorithm
paramParameters to parse
Return values
rcReturn status code

Definition at line 802 of file asn1.c.

803 {
804 struct cipher_algorithm *cipher = algorithm->cipher;
805
806 /* Sanity check */
807 assert ( cipher != NULL );
808
809 /* Enter parameters */
810 asn1_enter ( params, ASN1_OCTET_STRING );
811
812 /* Check length */
813 if ( params->len != cipher->blocksize )
814 return -EINVAL;
815
816 return 0;
817}
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition asn1.h:69
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define EINVAL
Invalid argument.
Definition errno.h:429
A cipher algorithm.
Definition crypto.h:58
size_t blocksize
Block size.
Definition crypto.h:68

References algorithm, asn1_enter(), ASN1_OCTET_STRING, assert, cipher_algorithm::blocksize, EINVAL, asn1_cursor::len, and NULL.

◆ asn1_parse_gcm()

int asn1_parse_gcm ( struct asn1_algorithm *algorithm __unused,
struct asn1_cursor * params )

Parse ASN.1 GCM cipher parameters.

Parameters
algorithmAlgorithm
paramParameters to parse
Return values
rcReturn status code

Definition at line 826 of file asn1.c.

827 {
828
829 /* Enter parameters */
830 asn1_enter ( params, ASN1_SEQUENCE );
831
832 /* Enter nonce */
833 return asn1_enter ( params, ASN1_OCTET_STRING );
834}

References __unused, algorithm, asn1_enter(), ASN1_OCTET_STRING, and ASN1_SEQUENCE.

◆ asn1_generalized_time()

int asn1_generalized_time ( const struct asn1_cursor * cursor,
time_t * time )

Parse ASN.1 GeneralizedTime.

Parameters
cursorASN.1 cursor
timeTime to fill in
Return values
rcReturn status code

RFC 5280 section 4.1.2.5 places several restrictions on the allowed formats for UTCTime and GeneralizedTime, and mandates the interpretation of centuryless year values.

Definition at line 847 of file asn1.c.

847 {
848 struct asn1_cursor contents;
849 unsigned int have_century;
850 unsigned int type;
851 union {
852 struct {
856 uint8_t day;
857 uint8_t hour;
858 uint8_t minute;
859 uint8_t second;
860 } __attribute__ (( packed )) named;
861 uint8_t raw[7];
862 } pairs;
863 struct tm tm;
864 const uint8_t *data;
865 size_t remaining;
866 unsigned int tens;
867 unsigned int units;
868 unsigned int i;
869 int rc;
870
871 /* Determine time format utcTime/generalizedTime */
872 memcpy ( &contents, cursor, sizeof ( contents ) );
873 type = asn1_type ( &contents );
874 switch ( type ) {
875 case ASN1_UTC_TIME:
876 have_century = 0;
877 break;
879 have_century = 1;
880 break;
881 default:
882 DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
883 cursor, type );
884 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
885 return -EINVAL_ASN1_TIME;
886 }
887
888 /* Enter utcTime/generalizedTime */
889 if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
890 DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
891 ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
892 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
893 return rc;
894 }
895
896 /* Parse digit string a pair at a time */
897 memset ( &pairs, 0, sizeof ( pairs ) );
898 data = contents.data;
899 remaining = contents.len;
900 for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
901 if ( remaining < 2 ) {
902 /* Some certificates violate the X.509 RFC by
903 * omitting the "seconds" value.
904 */
905 if ( i == ( sizeof ( pairs.raw ) - 1 ) )
906 break;
907 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
908 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
909 return -EINVAL_ASN1_TIME;
910 }
911 tens = data[0];
912 units = data[1];
913 if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
914 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
915 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
916 return -EINVAL_ASN1_TIME;
917 }
918 pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
919 data += 2;
920 remaining -= 2;
921 }
922
923 /* Determine century if applicable */
924 if ( ! have_century )
925 pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
926
927 /* Check for trailing "Z" */
928 if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
929 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
930 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
931 return -EINVAL_ASN1_TIME;
932 }
933
934 /* Fill in time */
935 tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
936 pairs.named.year );
937 tm.tm_mon = ( pairs.named.month - 1 );
938 tm.tm_mday = pairs.named.day;
939 tm.tm_hour = pairs.named.hour;
940 tm.tm_min = pairs.named.minute;
941 tm.tm_sec = pairs.named.second;
942
943 /* Convert to seconds since the Epoch */
944 *time = mktime ( &tm );
945
946 return 0;
947}
__be32 raw[7]
Definition CIB_PRM.h:0
#define EINVAL_ASN1_TIME
Definition asn1.c:136
#define ASN1_UTC_TIME
ASN.1 UTC time.
Definition asn1.h:84
#define ASN1_GENERALIZED_TIME
ASN.1 generalized time.
Definition asn1.h:87
static int isdigit(int character)
Check if character is a decimal digit.
Definition ctype.h:30
void * memset(void *dest, int character, size_t len) __nonnull
Broken-down time.
Definition time.h:16
int tm_mon
Month of year [0,11].
Definition time.h:26
int tm_year
Years since 1900.
Definition time.h:28
int tm_hour
Hour [0,23].
Definition time.h:22
int tm_sec
Seconds [0,60].
Definition time.h:18
int tm_mday
Day of month [1,31].
Definition time.h:24
int tm_min
Minutes [0,59].
Definition time.h:20
time_t mktime(struct tm *tm)
Calculate seconds since the Epoch.
Definition time.c:119
uint8_t month
Month (BCD).
Definition ucode.h:7
uint8_t day
Day (BCD).
Definition ucode.h:5
uint8_t year
Year (BCD).
Definition ucode.h:1
uint8_t century
Century (BCD).
Definition ucode.h:3

References __attribute__, asn1_enter(), ASN1_GENERALIZED_TIME, asn1_type(), ASN1_UTC_TIME, century, asn1_cursor::data, data, day, DBGC, DBGC_HDA, EINVAL_ASN1_TIME, isdigit(), asn1_cursor::len, memcpy(), memset(), mktime(), month, raw, rc, tm::tm_hour, tm::tm_mday, tm::tm_min, tm::tm_mon, tm::tm_sec, tm::tm_year, type, and year.

Referenced by ocsp_parse_responses(), and x509_parse_validity().

◆ asn1_header()

size_t asn1_header ( struct asn1_builder_header * header,
unsigned int type,
size_t len )
static

Construct ASN.1 header.

Parameters
headerASN.1 builder header
typeType
lenContent length
Return values
header_lenHeader length

Definition at line 957 of file asn1.c.

958 {
959 unsigned int header_len = 2;
960 unsigned int len_len = 0;
961 size_t temp;
962
963 /* Construct header */
964 header->type = type;
965 if ( len < 0x80 ) {
966 header->length[0] = len;
967 } else {
968 for ( temp = len ; temp ; temp >>= 8 )
969 len_len++;
970 header->length[0] = ( 0x80 | len_len );
971 header_len += len_len;
972 for ( temp = len ; temp ; temp >>= 8 )
973 header->length[len_len--] = ( temp & 0xff );
974 }
975
976 return header_len;
977}
struct ena_llq_option header
Header locations.
Definition ena.h:5

References header, len, and type.

Referenced by asn1_prepend(), and asn1_wrap().

◆ asn1_grow()

int asn1_grow ( struct asn1_builder * builder,
size_t extra )

Grow ASN.1 builder.

Parameters
builderASN.1 builder
extraExtra space to prepend
Return values
rcReturn status code

Definition at line 986 of file asn1.c.

986 {
987 size_t new_len;
988 void *new;
989
990 /* As with the ASN1 parsing functions, make errors permanent */
991 if ( builder->len && ! builder->data )
992 return -ENOMEM;
993
994 /* Reallocate data buffer */
995 new_len = ( builder->len + extra );
996 new = realloc ( builder->data, new_len );
997 if ( ! new ) {
998 zfree ( builder->data );
999 builder->data = NULL;
1000 return -ENOMEM;
1001 }
1002 builder->data = new;
1003
1004 /* Move existing data to end of buffer */
1005 memmove ( ( builder->data + extra ), builder->data, builder->len );
1006 builder->len = new_len;
1007
1008 return 0;
1009}
#define ENOMEM
Not enough space.
Definition errno.h:535
uint8_t extra
Signature extra byte.
Definition smbios.h:6
void * memmove(void *dest, const void *src, size_t len) __nonnull
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:607
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:682
void * data
Data.
Definition asn1.h:36
size_t len
Length of data.
Definition asn1.h:38

References asn1_builder::data, ENOMEM, extra, asn1_builder::len, memmove(), NULL, realloc(), and zfree().

Referenced by asn1_prepend(), asn1_prepend_raw(), asn1_wrap(), rsa_pkcs1_decrypt(), rsa_pkcs1_encrypt(), and rsa_sign().

◆ asn1_prepend_raw()

int asn1_prepend_raw ( struct asn1_builder * builder,
const void * data,
size_t len )

Prepend raw data to ASN.1 builder.

Parameters
builderASN.1 builder
dataData to prepend
lenLength of data to prepend
Return values
rcReturn status code

Definition at line 1019 of file asn1.c.

1020 {
1021 int rc;
1022
1023 /* Grow buffer */
1024 if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
1025 return rc;
1026
1027 /* Populate data buffer */
1028 memcpy ( builder->data, data, len );
1029
1030 return 0;
1031}
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:986

References asn1_grow(), asn1_builder::data, data, len, memcpy(), and rc.

Referenced by icert_cert(), icert_certs(), ocsp_request(), tls_send_certificate_verify(), and tls_send_client_key_exchange_pubkey().

◆ asn1_prepend()

int asn1_prepend ( struct asn1_builder * builder,
unsigned int type,
const void * data,
size_t len )

Prepend data to ASN.1 builder.

Parameters
builderASN.1 builder
typeType
dataData to prepend
lenLength of data to prepend
Return values
rcReturn status code

Definition at line 1042 of file asn1.c.

1043 {
1045 size_t header_len;
1046 int rc;
1047
1048 /* Construct header */
1049 header_len = asn1_header ( &header, type, len );
1050
1051 /* Grow buffer */
1052 if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
1053 return rc;
1054
1055 /* Populate data buffer */
1056 memcpy ( builder->data, &header, header_len );
1057 memcpy ( ( builder->data + header_len ), data, len );
1058
1059 return 0;
1060}
static size_t asn1_header(struct asn1_builder_header *header, unsigned int type, size_t len)
Construct ASN.1 header.
Definition asn1.c:957
An ASN.1 header.
Definition asn1.h:49

References asn1_grow(), asn1_header(), asn1_builder::data, data, header, len, memcpy(), rc, and type.

Referenced by ecdsa_prepend_signature(), icert_certs(), and ocsp_request().

◆ asn1_wrap()

int asn1_wrap ( struct asn1_builder * builder,
unsigned int type )

Wrap ASN.1 builder.

Parameters
builderASN.1 builder
typeType
Return values
rcReturn status code

Definition at line 1069 of file asn1.c.

1069 {
1071 size_t header_len;
1072 int rc;
1073
1074 /* Construct header */
1075 header_len = asn1_header ( &header, type, builder->len );
1076
1077 /* Grow buffer */
1078 if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
1079 return rc;
1080
1081 /* Populate data buffer */
1082 memcpy ( builder->data, &header, header_len );
1083
1084 return 0;
1085}

References asn1_grow(), asn1_header(), asn1_builder::data, header, asn1_builder::len, memcpy(), rc, and type.

Referenced by ecdsa_sign(), icert_cert(), icert_certs(), and ocsp_request().

◆ image_asn1()

int image_asn1 ( struct image * image,
size_t offset,
struct asn1_cursor ** cursor )

Extract ASN.1 object from image.

Parameters
imageImage
offsetOffset within image
cursorASN.1 cursor to fill in
Return values
nextOffset to next image, or negative error

The caller is responsible for eventually calling free() on the allocated ASN.1 cursor.

Definition at line 1098 of file asn1.c.

1099 {
1100 int next;
1101 int rc;
1102
1103 /* Sanity check */
1105
1106 /* Check that this image can be used to extract an ASN.1 object */
1107 if ( ! ( image->type && image->type->asn1 ) )
1108 return -ENOTSUP;
1109
1110 /* Try creating ASN.1 cursor */
1111 next = image->type->asn1 ( image, offset, cursor );
1112 if ( next < 0 ) {
1113 rc = next;
1114 DBGC ( image, "IMAGE %s could not extract ASN.1 object: %s\n",
1115 image->name, strerror ( rc ) );
1116 return rc;
1117 }
1118
1119 return next;
1120}
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint32_t next
Next descriptor address.
Definition dwmac.h:11
#define ENOTSUP
Operation not supported.
Definition errno.h:590
int(* asn1)(struct image *image, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from image.
Definition image.h:140
An executable image.
Definition image.h:24
struct image_type * type
Image type, if known.
Definition image.h:66
char * name
Name.
Definition image.h:38

References image_type::asn1, assert, DBGC, ENOTSUP, len, image::name, next, offset, rc, strerror(), and image::type.

Referenced by asn1_okx(), cms_message(), image_x509(), and REQUIRING_SYMBOL().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( image_asn1 )

References image_asn1().

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_asn1 )