diff options
Diffstat (limited to 'common/pem.c')
-rw-r--r-- | common/pem.c | 290 |
1 files changed, 0 insertions, 290 deletions
diff --git a/common/pem.c b/common/pem.c deleted file mode 100644 index 7fe0076..0000000 --- a/common/pem.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * The names of contributors to this software may not be - * used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * Author: Stef Walter <stefw@redhat.com> - */ - -#include "config.h" - -#include "compat.h" -#include "base64.h" -#include "buffer.h" -#include "debug.h" -#include "pem.h" - -#include <assert.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#define ARMOR_SUFF "-----" -#define ARMOR_SUFF_L 5 -#define ARMOR_PREF_BEGIN "-----BEGIN " -#define ARMOR_PREF_BEGIN_L 11 -#define ARMOR_PREF_END "-----END " -#define ARMOR_PREF_END_L 9 - -enum { - NONE = 0, - TRUSTED_CERTIFICATE, - CERTIFICATE -}; - -static const char * -pem_find_begin (const char *data, - size_t n_data, - char **type) -{ - const char *pref, *suff; - - /* Look for a prefix */ - pref = strnstr ((char *)data, ARMOR_PREF_BEGIN, n_data); - if (!pref) - return NULL; - - n_data -= (pref - data) + ARMOR_PREF_BEGIN_L; - data = pref + ARMOR_PREF_BEGIN_L; - - /* Look for the end of that begin */ - suff = strnstr ((char *)data, ARMOR_SUFF, n_data); - if (!suff) - return NULL; - - /* Make sure on the same line */ - if (memchr (pref, '\n', suff - pref)) - return NULL; - - if (type) { - pref += ARMOR_PREF_BEGIN_L; - assert (suff > pref); - *type = malloc (suff - pref + 1); - return_val_if_fail (*type != NULL, NULL); - memcpy (*type, pref, suff - pref); - (*type)[suff - pref] = 0; - } - - /* The byte after this ---BEGIN--- */ - return suff + ARMOR_SUFF_L; -} - -static const char * -pem_find_end (const char *data, - size_t n_data, - const char *type) -{ - const char *pref; - size_t n_type; - - /* Look for a prefix */ - pref = strnstr (data, ARMOR_PREF_END, n_data); - if (!pref) - return NULL; - - n_data -= (pref - data) + ARMOR_PREF_END_L; - data = pref + ARMOR_PREF_END_L; - - /* Next comes the type string */ - n_type = strlen (type); - if (n_type > n_data || strncmp ((char *)data, type, n_type) != 0) - return NULL; - - n_data -= n_type; - data += n_type; - - /* Next comes the suffix */ - if (ARMOR_SUFF_L > n_data || strncmp ((char *)data, ARMOR_SUFF, ARMOR_SUFF_L) != 0) - return NULL; - - /* The end of the data */ - return pref; -} - -static unsigned char * -pem_parse_block (const char *data, - size_t n_data, - size_t *n_decoded) -{ - const char *x, *hbeg, *hend; - const char *p, *end; - unsigned char *decoded; - size_t length; - int ret; - - assert (data != NULL); - assert (n_data != 0); - assert (n_decoded != NULL); - - p = data; - end = p + n_data; - - hbeg = hend = NULL; - - /* Try and find a pair of blank lines with only white space between */ - while (hend == NULL) { - x = memchr (p, '\n', end - p); - if (!x) - break; - ++x; - while (isspace (*x)) { - /* Found a second line, with only spaces between */ - if (*x == '\n') { - hbeg = data; - hend = x; - break; - /* Found a space between two lines */ - } else { - ++x; - } - } - - /* Try next line */ - p = x; - } - - /* Headers found? */ - if (hbeg && hend) { - data = hend; - n_data = end - data; - } - - length = (n_data * 3) / 4 + 1; - decoded = malloc (length); - return_val_if_fail (decoded != NULL, 0); - - ret = p11_b64_pton (data, n_data, decoded, length); - if (ret < 0) { - free (decoded); - return NULL; - } - - /* No need to parse headers for our use cases */ - - *n_decoded = ret; - return decoded; -} - -unsigned int -p11_pem_parse (const char *data, - size_t n_data, - p11_pem_sink sink, - void *user_data) -{ - const char *beg, *end; - unsigned int nfound = 0; - unsigned char *decoded = NULL; - size_t n_decoded = 0; - char *type; - - assert (data != NULL); - - while (n_data > 0) { - - /* This returns the first character after the PEM BEGIN header */ - beg = pem_find_begin (data, n_data, &type); - if (beg == NULL) - break; - - assert (type != NULL); - - /* This returns the character position before the PEM END header */ - end = pem_find_end (beg, n_data - (beg - data), type); - if (end == NULL) { - free (type); - break; - } - - if (beg != end) { - decoded = pem_parse_block (beg, end - beg, &n_decoded); - if (decoded) { - if (sink != NULL) - (sink) (type, decoded, n_decoded, user_data); - ++nfound; - free (decoded); - } - } - - free (type); - - /* Try for another block */ - end += ARMOR_SUFF_L; - n_data -= (const char *)end - (const char *)data; - data = end; - } - - return nfound; -} - -bool -p11_pem_write (const unsigned char *contents, - size_t length, - const char *type, - p11_buffer *buf) -{ - size_t estimate; - size_t prefix; - char *target; - int len; - - return_val_if_fail (contents || !length, false); - return_val_if_fail (type, false); - return_val_if_fail (buf, false); - - /* Estimate from base64 data. Algorithm from Glib reference */ - estimate = length * 4 / 3 + 7; - estimate += estimate / 64 + 1; - - p11_buffer_add (buf, ARMOR_PREF_BEGIN, ARMOR_PREF_BEGIN_L); - p11_buffer_add (buf, type, -1); - p11_buffer_add (buf, ARMOR_SUFF, ARMOR_SUFF_L); - - prefix = buf->len; - target = p11_buffer_append (buf, estimate); - return_val_if_fail (target != NULL, NULL); - - /* - * OpenSSL is absolutely certain that it wants its PEM base64 - * lines to be 64 characters in len. - */ - - len = p11_b64_ntop (contents, length, target, estimate, 64); - - assert (len > 0); - assert (len <= estimate); - buf->len = prefix + len; - - p11_buffer_add (buf, "\n", 1); - p11_buffer_add (buf, ARMOR_PREF_END, ARMOR_PREF_END_L); - p11_buffer_add (buf, type, -1); - p11_buffer_add (buf, ARMOR_SUFF, ARMOR_SUFF_L); - p11_buffer_add (buf, "\n", 1); - - return p11_buffer_ok (buf); -} |