pem_encode.c revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * CDDL HEADER START
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * The contents of this file are subject to the terms of the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Common Development and Distribution License (the "License").
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * You may not use this file except in compliance with the License.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * See the License for the specific language governing permissions
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * and limitations under the License.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * When distributing Covered Code, include this CDDL HEADER in each
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * If applicable, add the following below this CDDL HEADER, with the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * fields enclosed by brackets "[]" replaced with your own identifying
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * information: Portions Copyright [yyyy] [name of copyright owner]
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * CDDL HEADER END
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Use is subject to license terms.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#pragma ident "%Z%%M% %I% %E% SMI"
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * All rights reserved.
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 * 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 * 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 * Redistribution and use in source and binary forms, with or without
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * modification, are permitted provided that the following conditions
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 * 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 * 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/* pem_encode.c - PEM encoding routines */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysabcdefghijklmnopqrstuvwxyz0123456789+/";
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i, ret = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned long l;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i >= 3) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys l = (((unsigned long)f[0])<<16L)|
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys l = ((unsigned long)f[0])<<16L;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i == 2)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = '=';
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_EncodeUpdate(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned int total = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys j = PEM_EncodeBlock(out, ctx->enc_data, ctx->length);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_EncodeFinal(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned int ret = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (data == NULL || len == 0 || out == NULL || outlen == NULL)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while (len > 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys n = (int)((len > (PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i, ret = 0, a, b, c, d;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned long l;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* trim white space from the start of the line. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * strip off stuff at the end of the line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n-1]))))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (n%4 != 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (-1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (i = 0; i < n; i += 4) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (-1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys l = ((((unsigned long)a)<<18L)|
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (((unsigned long)b)<<12L)|
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (((unsigned long)c)<< 6L)|
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (((unsigned long)d)));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *(t++) = (unsigned char)(l)&0xff;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * -1 for error
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 0 for last line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * 1 for full line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_DecodeUpdate(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned char *d;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* last line of input. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* We parse the input data */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (i = 0; i < inl; i++) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* If the current line is > 80 characters, scream alot */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Get char and put it into the buffer */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* only save the good data :-) */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } else if (v == B64_ERROR) {
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 if (v == B64_CR) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * If we are at the end of input and it looks like a
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * line, process it.
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 /* There will never be more than two '=' */
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 if (n > 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (v < 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * This is the case where we have had a short
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * but valid input line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (seof >= 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysPEM_DecodeFinal(PEM_ENCODE_CTX *ctx, unsigned char *out, int *outl)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (-1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return (1);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int i, k, bl = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned char *dataB;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * get a line (ended at '\n'), which returns
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * number of bytes in the line
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i <= 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i <= 0) break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (unsigned char *)dataB, &bl, (unsigned char *)dataB, bl);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i < 0) {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys i = PEM_DecodeFinal(&ctx, (unsigned char *)&(dataB[bl]), &k);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (i < 0) {