99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*
d00756ccb34596a328f8a15d1965da5412d366d0wyllys * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Use is subject to license terms.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#pragma ident "%Z%%M% %I% %E% SMI"
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * All rights reserved.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * This package is an SSL implementation written
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * by Eric Young (eay@cryptsoft.com).
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * The implementation was written so as to conform with Netscapes SSL.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * This library is free for commercial and non-commercial use as long as
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * the following conditions are aheared to. The following conditions
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * apply to all code found in this distribution, be it the RC4, RSA,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * lhash, DES, etc., code; not just the SSL code. The SSL documentation
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * included with this distribution is covered by the same copyright terms
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * except that the holder is Tim Hudson (tjh@cryptsoft.com).
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Copyright remains Eric Young's, and as such any Copyright notices in
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * the code are not to be removed.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * If this package is used in a product, Eric Young should be given attribution
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * as the author of the parts of the library used.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * This can be in the form of a textual message at program startup or
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * in documentation (online or textual) provided with the package.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Redistribution and use in source and binary forms, with or without
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * modification, are permitted provided that the following conditions
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * are met:
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 1. Redistributions of source code must retain the copyright
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * notice, this list of conditions and the following disclaimer.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 2. Redistributions in binary form must reproduce the above copyright
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * notice, this list of conditions and the following disclaimer in the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * documentation and/or other materials provided with the distribution.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 3. All advertising materials mentioning features or use of this software
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * must display the following acknowledgement:
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * "This product includes cryptographic software written by
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Eric Young (eay@cryptsoft.com)"
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * The word 'cryptographic' can be left out if the rouines from the library
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * being used are not cryptographic related :-).
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 4. If you include any Windows specific code (or a derivative thereof) from
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * the apps directory (application code) you must include an acknowledgement:
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * SUCH DAMAGE.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * The licence and distribution terms for any publically available version or
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * derivative of this code cannot be changed. i.e. this code cannot simply be
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * copied and put under another distribution licence
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * [including the GNU Public Licence.]
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/* pem_encode.c - PEM encoding routines */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <stdlib.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <strings.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <sys/types.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <kmfapi.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <pem_encode.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysabcdefghijklmnopqrstuvwxyz0123456789+/";
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic unsigned char data_ascii2bin[128] = {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys};
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#define conv_ascii2bin(a) (data_ascii2bin[(a)&0x7f])
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysvoid
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_EncodeInit(PEM_ENCODE_CTX *ctx)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->length = 48;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->line_num = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysint
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i, ret = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned long l;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (i = dlen; i > 0; i -= 3) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i >= 3) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys l = (((unsigned long)f[0])<<16L)|
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (((unsigned long)f[1])<< 8L)|f[2];
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = conv_bin2ascii(l>>18L);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = conv_bin2ascii(l>>12L);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = conv_bin2ascii(l>> 6L);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = conv_bin2ascii(l);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys l = ((unsigned long)f[0])<<16L;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i == 2)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys l |= ((unsigned long)f[1]<<8L);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = conv_bin2ascii(l>>18L);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = conv_bin2ascii(l>>12L);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = (i == 1)?'=':conv_bin2ascii(l>> 6L);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = '=';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ret += 4;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys f += 3;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *t = '\0';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (ret);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysvoid
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_EncodeUpdate(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned char *in, int inl)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i, j;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned int total = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (inl == 0)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((ctx->num+inl) < ctx->length) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(&(ctx->enc_data[ctx->num]), in, inl);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num += inl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (ctx->num != 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = ctx->length-ctx->num;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(&(ctx->enc_data[ctx->num]), in, i);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys in += i;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys inl -= i;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys j = PEM_EncodeBlock(out, ctx->enc_data, ctx->length);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys out += j;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(out++) = '\n';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *out = '\0';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys total = j+1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while (inl >= ctx->length) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys j = PEM_EncodeBlock(out, in, ctx->length);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys in += ctx->length;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys inl -= ctx->length;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys out += j;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(out++) = '\n';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *out = '\0';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys total += j+1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (inl != 0)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(&(ctx->enc_data[0]), in, inl);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num = inl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outl = total;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysvoid
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_EncodeFinal(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned int ret = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (ctx->num != 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ret = PEM_EncodeBlock(out, ctx->enc_data, ctx->num);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys out[ret++] = '\n';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys out[ret] = '\0';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outl = ret;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysKMF_RETURN
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysDer2Pem(KMF_OBJECT_TYPE type, unsigned char *data,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int len, unsigned char **out, int *outlen)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int nlen, n, i, j, outl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned char *buf = NULL, *p = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PEM_ENCODE_CTX ctx;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *name = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (data == NULL || len == 0 || out == NULL || outlen == NULL)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (KMF_ERR_BAD_PARAMETER);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (type == KMF_CERT)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys name = PEM_STRING_X509;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (type == KMF_CSR)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys name = PEM_STRING_X509_REQ;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (type == KMF_CRL)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys name = PEM_STRING_X509_CRL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (KMF_ERR_BAD_OBJECT_TYPE);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PEM_EncodeInit(&ctx);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys nlen = strlen(name);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys buf = malloc(PEM_BUFSIZE*8);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (buf == NULL) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (KMF_ERR_MEMORY);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p = buf;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(p, "-----BEGIN ", 11);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += 11;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(p, name, nlen);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += nlen;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(p, "-----\n", 6);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += 6;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = j = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while (len > 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys n = (int)((len > (PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PEM_EncodeUpdate(&ctx, p, &outl, &(data[j]), n);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i += outl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys len -= n;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys j += n;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += outl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PEM_EncodeFinal(&ctx, p, &outl);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (outl > 0)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += outl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(p, "-----END ", 9);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += 9;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(p, name, nlen);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += nlen;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(p, "-----\n", 6);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys p += 6;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *out = buf;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outlen = i+outl+nlen*2+11+6+9+6;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (KMF_OK);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysint
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i, ret = 0, a, b, c, d;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned long l;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* trim white space from the start of the line. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys f++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys n--;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * strip off stuff at the end of the line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n-1]))))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys n--;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (n%4 != 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (-1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (i = 0; i < n; i += 4) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys a = conv_ascii2bin(*(f++));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys b = conv_ascii2bin(*(f++));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys c = conv_ascii2bin(*(f++));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys d = conv_ascii2bin(*(f++));
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (-1);
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee l = ((((unsigned long)a)<<18L) | (((unsigned long)b)<<12L) |
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee (((unsigned long)c)<< 6L) | (((unsigned long)d)));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = (unsigned char)(l>>16L)&0xff;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = (unsigned char)(l>> 8L)&0xff;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = (unsigned char)(l)&0xff;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ret += 3;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (ret);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysvoid
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_DecodeInit(PEM_ENCODE_CTX *ctx)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->length = 30;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->line_num = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->expect_nl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * -1 for error
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 0 for last line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 1 for full line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysint
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_DecodeUpdate(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned char *in, int inl)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int seof = -1, eof = 0, rv = -1, ret = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i, v, tmp, n, ln, exp_nl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned char *d;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys n = ctx->num;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys d = ctx->enc_data;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ln = ctx->line_num;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys exp_nl = ctx->expect_nl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* last line of input. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rv = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto end;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* We parse the input data */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (i = 0; i < inl; i++) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* If the current line is > 80 characters, scream alot */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (ln >= 80) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rv = -1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto end;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Get char and put it into the buffer */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys tmp = *(in++);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys v = conv_ascii2bin(tmp);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* only save the good data :-) */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (!B64_NOT_BASE64(v)) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys d[n++] = tmp;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ln++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else if (v == B64_ERROR) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rv = -1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto end;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * have we seen a '=' which is 'definitly' the last
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * input line. seof will point to the character that
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * holds it. and eof will hold how many characters to
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * chop off.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (tmp == '=') {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (seof == -1) seof = n;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys eof++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (v == B64_CR) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ln = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (exp_nl)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys continue;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* eoln */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (v == B64_EOLN) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ln = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (exp_nl) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys exp_nl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys continue;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys exp_nl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * If we are at the end of input and it looks like a
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * line, process it.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (((i+1) == inl) && (((n&3) == 0) || eof)) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys v = B64_EOF;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * In case things were given us in really small
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * records (so two '=' were given in separate
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * updates), eof may contain the incorrect number
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * of ending bytes to skip, so let's redo the count
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys eof = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (d[n-1] == '=') eof++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (d[n-2] == '=') eof++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* There will never be more than two '=' */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((v == B64_EOF) || (n >= 64)) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * This is needed to work correctly on 64 byte input
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * lines. We process the line and then need to
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * accept the '\n'
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((v != B64_EOF) && (n >= 64))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys exp_nl = 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (n > 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys v = PEM_DecodeBlock(out, d, n);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (v < 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rv = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto end;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys n = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ret += (v-eof);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys eof = 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys v = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * This is the case where we have had a short
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * but valid input line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((v < ctx->length) && eof) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rv = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto end;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->length = v;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (seof >= 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rv = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto end;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys out += v;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rv = 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysend:
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outl = ret;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num = n;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->line_num = ln;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->expect_nl = exp_nl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (rv);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysint
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_DecodeFinal(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (ctx->num != 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = PEM_DecodeBlock(out, ctx->enc_data, ctx->num);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i < 0)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (-1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ctx->num = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outl = i;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic int
d00756ccb34596a328f8a15d1965da5412d366d0wyllysget_line(unsigned char *in, int inlen, char *buf, int buflen)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys while ((i < inlen) && (i < buflen) && (in[i] != '\n')) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys buf[i] = in[i];
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys return (i);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysKMF_RETURN
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPem2Der(unsigned char *in, int inlen,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned char **out, int *outlen)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int kmf_rv = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PEM_ENCODE_CTX ctx;
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee int i, j, k, bl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char buf[2048];
73cc0e021f4115db3085cd78083c42c8be4559e3wyllys char *nameB = NULL;
73cc0e021f4115db3085cd78083c42c8be4559e3wyllys unsigned char *dataB = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int total = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (in == NULL || inlen == 0 || out == NULL)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (KMF_ERR_BAD_PARAMETER);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memset(buf, 0, sizeof (buf));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys while (total < inlen) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * get a line (ended at '\n'), which returns
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * number of bytes in the line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
d00756ccb34596a328f8a15d1965da5412d366d0wyllys i = get_line(in + total, inlen - total, buf, sizeof (buf));
d00756ccb34596a328f8a15d1965da5412d366d0wyllys if (i == 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kmf_rv = KMF_ERR_ENCODING;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee j = i;
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee while ((j >= 0) && (buf[j] <= ' ')) j--;
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee buf[++j] = '\n';
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee buf[++j] = '\0';
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee total += i + 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (strncmp(buf, "-----BEGIN ", 11) == 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = strlen(&(buf[11]));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (strncmp(&(buf[11+i-6]), "-----\n", 6) != 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys continue;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((nameB = malloc(i+9)) == NULL) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kmf_rv = KMF_ERR_MEMORY;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memcpy(nameB, &(buf[11]), i-6);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys nameB[i-6] = '\0';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys bl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((dataB = malloc(2048)) == NULL) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kmf_rv = KMF_ERR_MEMORY;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys dataB[0] = '\0';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys while (total < inlen) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (void) memset(buf, 0, 1024);
d00756ccb34596a328f8a15d1965da5412d366d0wyllys i = get_line(in+total, inlen - total, buf, sizeof (buf));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys if (i == 0) break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee j = i;
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee while ((j >= 0) && (buf[j] <= ' '))
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee j--;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee buf[++j] = '\n';
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee buf[++j] = '\0';
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee total += i + 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (buf[0] == '\n') break;
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee if ((dataB = realloc(dataB, bl+j+9)) == NULL) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kmf_rv = KMF_ERR_MEMORY;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (strncmp(buf, "-----END ", 9) == 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee (void) memcpy(&(dataB[bl]), buf, j);
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee dataB[bl+j] = '\0';
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee bl += j;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
d00756ccb34596a328f8a15d1965da5412d366d0wyllys if (nameB == NULL)
d00756ccb34596a328f8a15d1965da5412d366d0wyllys goto err;
d00756ccb34596a328f8a15d1965da5412d366d0wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = strlen(nameB);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((strncmp(buf, "-----END ", 9) != 0) ||
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee (strncmp(nameB, &(buf[9]), i) != 0) ||
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee (strncmp(&(buf[9+i]), "-----", 5) != 0)) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kmf_rv = KMF_ERR_ENCODING;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PEM_DecodeInit(&ctx);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = PEM_DecodeUpdate(&ctx,
fbcec90110655a00a2d5c9bdfaf87c7b476a4902hylee (unsigned char *)dataB, &bl, (unsigned char *)dataB, bl);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i < 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kmf_rv = KMF_ERR_ENCODING;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = PEM_DecodeFinal(&ctx, (unsigned char *)&(dataB[bl]), &k);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i < 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys kmf_rv = KMF_ERR_ENCODING;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys bl += k;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (bl == 0) goto err;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *out = (unsigned char *)dataB;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *outlen = bl;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllyserr:
73cc0e021f4115db3085cd78083c42c8be4559e3wyllys if (nameB != NULL)
73cc0e021f4115db3085cd78083c42c8be4559e3wyllys free(nameB);
73cc0e021f4115db3085cd78083c42c8be4559e3wyllys if (kmf_rv != KMF_OK && dataB != NULL)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys free(dataB);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (kmf_rv);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}