iPXE
Functions
pem.c File Reference

PEM-encoded ASN.1 data. More...

#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/asn1.h>
#include <ipxe/base64.h>
#include <ipxe/uaccess.h>
#include <ipxe/image.h>
#include <ipxe/pem.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static size_t pem_next (userptr_t data, size_t len, size_t offset)
 Locate next line.
static int pem_marker (userptr_t data, size_t len, size_t offset, const char *marker)
 Locate boundary marker line.
int pem_asn1 (userptr_t data, size_t len, size_t offset, struct asn1_cursor **cursor)
 Extract ASN.1 object from PEM data.
static int pem_image_probe (struct image *image)
 Probe PEM image.
static int pem_image_asn1 (struct image *image, size_t offset, struct asn1_cursor **cursor)
 Extract ASN.1 object from image.
struct image_type pem_image_type __image_type (PROBE_NORMAL)
 PEM image type.

Detailed Description

PEM-encoded ASN.1 data.

Definition in file pem.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static size_t pem_next ( userptr_t  data,
size_t  len,
size_t  offset 
) [static]

Locate next line.

Parameters:
dataPEM data
lenLength of PEM data
offsetStarting offset
Return values:
nextOffset to next line

Definition at line 49 of file pem.c.

References len, and memchr_user().

Referenced by pem_asn1(), and pem_marker().

                                                                     {
        off_t eol;

        /* Find and skip next newline character, if any */
        eol = memchr_user ( data, offset, '\n', ( len - offset ) );
        if ( eol < 0 )
                return len;
        return ( eol + 1 );
}
static int pem_marker ( userptr_t  data,
size_t  len,
size_t  offset,
const char *  marker 
) [static]

Locate boundary marker line.

Parameters:
dataPEM data
lenLength of PEM data
offsetStarting offset
markerBoundary marker
Return values:
offsetOffset to boundary marker line, or negative error

Definition at line 68 of file pem.c.

References assert, copy_from_user(), ENOENT, memcmp(), offset, pem_next(), and strlen().

Referenced by pem_asn1(), and pem_image_probe().

                                             {
        char buf[ strlen ( marker ) ];

        /* Sanity check */
        assert ( offset <= len );

        /* Scan for marker at start of line */
        while ( offset < len ) {

                /* Check for marker */
                if ( ( len - offset ) < sizeof ( buf ) )
                        break;
                copy_from_user ( buf, data, offset, sizeof ( buf ) );
                if ( memcmp ( buf, marker, sizeof ( buf ) ) == 0 )
                        return offset;

                /* Move to next line */
                offset = pem_next ( data, len, offset );
                assert ( offset <= len );
        }

        return -ENOENT;
}
int pem_asn1 ( userptr_t  data,
size_t  len,
size_t  offset,
struct asn1_cursor **  cursor 
)

Extract ASN.1 object from PEM data.

Parameters:
dataPEM data
lenLength of PEM data
offsetOffset within data
cursorASN.1 cursor to fill in
Return values:
nextOffset to next object, or negative error

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

Definition at line 105 of file pem.c.

References assert, base64_decode(), base64_decoded_max_len(), copy_from_user(), DBGC, end, ENOMEM, free, len, malloc(), NULL, offset, PEM_BEGIN, PEM_END, pem_marker(), pem_next(), rc, and strerror().

Referenced by pem_image_asn1().

                                             {
        size_t encoded_len;
        size_t decoded_max_len;
        char *encoded;
        void *decoded;
        int decoded_len;
        int begin;
        int end;
        int rc;

        /* Locate and skip BEGIN marker */
        begin = pem_marker ( data, len, offset, PEM_BEGIN );
        if ( begin < 0 ) {
                rc = begin;
                DBGC ( data, "PEM [%#zx,%#zx) missing BEGIN marker: %s\n",
                       offset, len, strerror ( rc ) );
                goto err_begin;
        }
        begin = pem_next ( data, len, begin );

        /* Locate and skip END marker */
        end = pem_marker ( data, len, begin, PEM_END );
        if ( end < 0 ) {
                rc = end;
                DBGC ( data, "PEM [%#zx,%#zx) missing END marker: %s\n",
                       offset, len, strerror ( rc ) );
                goto err_end;
        }
        encoded_len = ( end - begin );
        end = pem_next ( data, len, end );

        /* Extract Base64-encoded data */
        encoded = malloc ( encoded_len + 1 /* NUL */ );
        if ( ! encoded ) {
                rc = -ENOMEM;
                goto err_alloc_encoded;
        }
        copy_from_user ( encoded, data, begin, encoded_len );
        encoded[encoded_len] = '\0';

        /* Allocate cursor and data buffer */
        decoded_max_len = base64_decoded_max_len ( encoded );
        *cursor = malloc ( sizeof ( **cursor ) + decoded_max_len );
        if ( ! *cursor ) {
                rc = -ENOMEM;
                goto err_alloc_cursor;
        }
        decoded = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );

        /* Decode Base64-encoded data */
        decoded_len = base64_decode ( encoded, decoded, decoded_max_len );
        if ( decoded_len < 0 ) {
                rc = decoded_len;
                DBGC ( data, "PEM could not decode: %s\n", strerror ( rc ) );
                goto err_decode;
        }
        (*cursor)->data = decoded;
        (*cursor)->len = decoded_len;
        assert ( (*cursor)->len <= decoded_max_len );

        /* Free Base64-encoded data */
        free ( encoded );

        /* Update offset and skip any unencapsulated trailer */
        offset = end;
        if ( pem_marker ( data, len, offset, PEM_BEGIN ) < 0 )
                offset = len;

        return offset;

 err_decode:
        free ( *cursor );
        *cursor = NULL;
 err_alloc_cursor:
        free ( encoded );
 err_alloc_encoded:
 err_end:
 err_begin:
        return rc;
}
static int pem_image_probe ( struct image image) [static]

Probe PEM image.

Parameters:
imagePEM image
Return values:
rcReturn status code

Definition at line 193 of file pem.c.

References image::data, DBGC, image::len, image::name, offset, PEM_BEGIN, pem_marker(), rc, and strerror().

                                                   {
        int offset;
        int rc;

        /* Check that image contains a BEGIN marker */
        if ( ( offset = pem_marker ( image->data, image->len, 0,
                                     PEM_BEGIN ) ) < 0 ) {
                rc = offset;
                DBGC ( image, "PEM %s has no BEGIN marker: %s\n",
                       image->name, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int pem_image_asn1 ( struct image image,
size_t  offset,
struct asn1_cursor **  cursor 
) [static]

Extract ASN.1 object from image.

Parameters:
imagePEM image
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 220 of file pem.c.

References image::data, DBGC, image::len, image::name, next, pem_asn1(), rc, and strerror().

                                                          {
        int next;
        int rc;

        /* Extract ASN.1 object */
        if ( ( next = pem_asn1 ( image->data, image->len, offset,
                                 cursor ) ) < 0 ) {
                rc = next;
                DBGC ( image, "PEM %s could not extract ASN.1: %s\n",
                       image->name, strerror ( rc ) );
                return rc;
        }

        return next;
}
struct image_type pem_image_type __image_type ( PROBE_NORMAL  ) [read]

PEM image type.