Example #1
0
int PEM_write_bio(BIO *bp, const char *name, const char *header,
                  const unsigned char *data, long len)
{
    int nlen, n, i, j, outl;
    unsigned char *buf = NULL;
    EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
    int reason = ERR_R_BUF_LIB;

    if (ctx == NULL) {
        reason = ERR_R_MALLOC_FAILURE;
        goto err;
    }

    EVP_EncodeInit(ctx);
    nlen = strlen(name);

    if ((BIO_write(bp, "-----BEGIN ", 11) != 11) ||
        (BIO_write(bp, name, nlen) != nlen) ||
        (BIO_write(bp, "-----\n", 6) != 6))
        goto err;

    i = strlen(header);
    if (i > 0) {
        if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1))
            goto err;
    }

    buf = OPENSSL_malloc(PEM_BUFSIZE * 8);
    if (buf == NULL) {
        reason = ERR_R_MALLOC_FAILURE;
        goto err;
    }

    i = j = 0;
    while (len > 0) {
        n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len);
        if (!EVP_EncodeUpdate(ctx, buf, &outl, &(data[j]), n))
            goto err;
        if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl))
            goto err;
        i += outl;
        len -= n;
        j += n;
    }
    EVP_EncodeFinal(ctx, buf, &outl);
    if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl))
        goto err;
    if ((BIO_write(bp, "-----END ", 9) != 9) ||
        (BIO_write(bp, name, nlen) != nlen) ||
        (BIO_write(bp, "-----\n", 6) != 6))
        goto err;
    OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
    EVP_ENCODE_CTX_free(ctx);
    return (i + outl);
 err:
    OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
    EVP_ENCODE_CTX_free(ctx);
    PEMerr(PEM_F_PEM_WRITE_BIO, reason);
    return (0);
}
Example #2
0
/* {{{ proto string Crypto\Base64::decode(string $data)
	Decodes base64 string $data to raw encoding */
PHP_CRYPTO_METHOD(Base64, decode)
{
	char *in;
	phpc_str_size_t in_len;
	int real_len, update_len, final_len;
	PHPC_STR_DECLARE(out);
	EVP_ENCODE_CTX *ctx;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in, &in_len) == FAILURE) {
		return;
	}

	ctx = EVP_ENCODE_CTX_new();
	php_crypto_base64_decode_init(ctx);
	real_len = EVP_DECODE_LENGTH(in_len);
	PHPC_STR_ALLOC(out, real_len);

	if (php_crypto_base64_decode_update(ctx, PHPC_STR_VAL(out),
			&update_len, in, in_len TSRMLS_CC) == FAILURE) {
		EVP_ENCODE_CTX_free(ctx);
		RETURN_FALSE;
	}
	php_crypto_base64_decode_finish(ctx, PHPC_STR_VAL(out), &final_len);
	final_len += update_len;
	if (real_len > final_len) {
		PHPC_STR_REALLOC(out, final_len);
	}
	EVP_ENCODE_CTX_free(ctx);
	PHPC_STR_VAL(out)[final_len] = '\0';
	PHPC_STR_RETURN(out);
}
Example #3
0
static int b64_new(BIO *bi)
{
    BIO_B64_CTX *ctx;

    ctx = OPENSSL_zalloc(sizeof(*ctx));
    if (ctx == NULL)
        return (0);

    ctx->cont = 1;
    ctx->start = 1;
    ctx->base64 = EVP_ENCODE_CTX_new();
    bi->init = 1;
    bi->ptr = (char *)ctx;
    bi->flags = 0;
    bi->num = 0;
    return (1);
}
Example #4
0
/*
 * Convert a raw byte string into a null-terminated base64 ASCII string.
 * Returns 1 on success or 0 on error.
 */
static int t_tob64(char *dst, const unsigned char *src, int size)
{
    EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
    int outl = 0, outl2 = 0;
    unsigned char pad[2] = {0, 0};
    size_t leadz = 0;

    if (ctx == NULL)
        return 0;

    EVP_EncodeInit(ctx);
    evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_NO_NEWLINES
                                  | EVP_ENCODE_CTX_USE_SRP_ALPHABET);

    /*
     * We pad at the front with zero bytes until the length is a multiple of 3
     * so that EVP_EncodeUpdate/EVP_EncodeFinal does not add any of its own "="
     * padding
     */
    leadz = 3 - (size % 3);
    if (leadz != 3
            && !EVP_EncodeUpdate(ctx, (unsigned char *)dst, &outl, pad,
                                 leadz)) {
        EVP_ENCODE_CTX_free(ctx);
        return 0;
    }

    if (!EVP_EncodeUpdate(ctx, (unsigned char *)dst + outl, &outl2, src,
                          size)) {
        EVP_ENCODE_CTX_free(ctx);
        return 0;
    }
    outl += outl2;
    EVP_EncodeFinal(ctx, (unsigned char *)dst + outl, &outl2);
    outl += outl2;

    /* Strip the encoded padding at the front */
    if (leadz != 3) {
        memmove(dst, dst + leadz, outl - leadz);
        dst[outl - leadz] = '\0';
    }

    EVP_ENCODE_CTX_free(ctx);
    return 1;
}
Example #5
0
static int b64_new(BIO *bi)
{
    BIO_B64_CTX *ctx;

    ctx = OPENSSL_zalloc(sizeof(*ctx));
    if (ctx == NULL)
        return 0;

    ctx->cont = 1;
    ctx->start = 1;
    ctx->base64 = EVP_ENCODE_CTX_new();
    if (ctx->base64 == NULL) {
        OPENSSL_free(ctx);
        return 0;
    }

    BIO_set_data(bi, ctx);
    BIO_set_init(bi, 1);

    return 1;
}
Example #6
0
/**
 * Read in PEM-formatted data from the given BIO.
 *
 * By nature of the PEM format, all content must be printable ASCII (except
 * for line endings).  Other characters are malformed input and will be rejected.
 */
int PEM_read_bio_ex(BIO *bp, char **name_out, char **header,
                    unsigned char **data, long *len_out, unsigned int flags)
{
    EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
    const BIO_METHOD *bmeth;
    BIO *headerB = NULL, *dataB = NULL;
    char *name = NULL;
    int len, taillen, headerlen, ret = 0;
    BUF_MEM * buf_mem;

    if (ctx == NULL) {
        PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE);
        return 0;
    }

    *len_out = 0;
    *name_out = *header = NULL;
    *data = NULL;
    if ((flags & PEM_FLAG_EAY_COMPATIBLE) && (flags & PEM_FLAG_ONLY_B64)) {
        /* These two are mutually incompatible; bail out. */
        PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_PASSED_INVALID_ARGUMENT);
        goto end;
    }
    bmeth = (flags & PEM_FLAG_SECURE) ? BIO_s_secmem() : BIO_s_mem();

    headerB = BIO_new(bmeth);
    dataB = BIO_new(bmeth);
    if (headerB == NULL || dataB == NULL) {
        PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE);
        goto end;
    }

    if (!get_name(bp, &name, flags))
        goto end;
    if (!get_header_and_data(bp, &headerB, &dataB, name, flags))
        goto end;

    EVP_DecodeInit(ctx);
    BIO_get_mem_ptr(dataB, &buf_mem);
    len = buf_mem->length;
    if (EVP_DecodeUpdate(ctx, (unsigned char*)buf_mem->data, &len,
                         (unsigned char*)buf_mem->data, len) < 0
            || EVP_DecodeFinal(ctx, (unsigned char*)&(buf_mem->data[len]),
                               &taillen) < 0) {
        PEMerr(PEM_F_PEM_READ_BIO_EX, PEM_R_BAD_BASE64_DECODE);
        goto end;
    }
    len += taillen;
    buf_mem->length = len;

    /* There was no data in the PEM file; avoid malloc(0). */
    if (len == 0)
        goto end;
    headerlen = BIO_get_mem_data(headerB, NULL);
    *header = pem_malloc(headerlen + 1, flags);
    *data = pem_malloc(len, flags);
    if (*header == NULL || *data == NULL) {
        pem_free(*header, flags, 0);
        pem_free(*data, flags, 0);
        goto end;
    }
    BIO_read(headerB, *header, headerlen);
    (*header)[headerlen] = '\0';
    BIO_read(dataB, *data, len);
    *len_out = len;
    *name_out = name;
    name = NULL;
    ret = 1;

end:
    EVP_ENCODE_CTX_free(ctx);
    pem_free(name, flags, 0);
    BIO_free(headerB);
    BIO_free(dataB);
    return ret;
}
Example #7
0
/*
 * Convert a base64 string into raw byte array representation.
 * Returns the length of the decoded data, or -1 on error.
 */
static int t_fromb64(unsigned char *a, size_t alen, const char *src)
{
    EVP_ENCODE_CTX *ctx;
    int outl = 0, outl2 = 0;
    size_t size, padsize;
    const unsigned char *pad = (const unsigned char *)"00";

    while (*src == ' ' || *src == '\t' || *src == '\n')
        ++src;
    size = strlen(src);
    padsize = 4 - (size & 3);
    padsize &= 3;

    /* Four bytes in src become three bytes output. */
    if (size > INT_MAX || ((size + padsize) / 4) * 3 > alen)
        return -1;

    ctx = EVP_ENCODE_CTX_new();
    if (ctx == NULL)
        return -1;

    /*
     * This should never occur because 1 byte of data always requires 2 bytes of
     * encoding, i.e.
     *  0 bytes unencoded = 0 bytes encoded
     *  1 byte unencoded  = 2 bytes encoded
     *  2 bytes unencoded = 3 bytes encoded
     *  3 bytes unencoded = 4 bytes encoded
     *  4 bytes unencoded = 6 bytes encoded
     *  etc
     */
    if (padsize == 3) {
        outl = -1;
        goto err;
    }

    /* Valid padsize values are now 0, 1 or 2 */

    EVP_DecodeInit(ctx);
    evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_USE_SRP_ALPHABET);

    /* Add any encoded padding that is required */
    if (padsize != 0
            && EVP_DecodeUpdate(ctx, a, &outl, pad, padsize) < 0) {
        outl = -1;
        goto err;
    }
    if (EVP_DecodeUpdate(ctx, a, &outl2, (const unsigned char *)src, size) < 0) {
        outl = -1;
        goto err;
    }
    outl += outl2;
    EVP_DecodeFinal(ctx, a + outl, &outl2);
    outl += outl2;

    /* Strip off the leading padding */
    if (padsize != 0) {
        if ((int)padsize >= outl) {
            outl = -1;
            goto err;
        }

        /*
         * If we added 1 byte of padding prior to encoding then we have 2 bytes
         * of "real" data which gets spread across 4 encoded bytes like this:
         *   (6 bits pad)(2 bits pad | 4 bits data)(6 bits data)(6 bits data)
         * So 1 byte of pre-encoding padding results in 1 full byte of encoded
         * padding.
         * If we added 2 bytes of padding prior to encoding this gets encoded
         * as:
         *   (6 bits pad)(6 bits pad)(4 bits pad | 2 bits data)(6 bits data)
         * So 2 bytes of pre-encoding padding results in 2 full bytes of encoded
         * padding, i.e. we have to strip the same number of bytes of padding
         * from the encoded data as we added to the pre-encoded data.
         */
        memmove(a, a + padsize, outl - padsize);
        outl -= padsize;
    }

 err:
    EVP_ENCODE_CTX_free(ctx);

    return outl;
}
Example #8
0
int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
                 long *len)
{
    EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
    int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
    char buf[256];
    BUF_MEM *nameB;
    BUF_MEM *headerB;
    BUF_MEM *dataB, *tmpB;

    if (ctx == NULL) {
        PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
        return (0);
    }

    nameB = BUF_MEM_new();
    headerB = BUF_MEM_new();
    dataB = BUF_MEM_new();
    if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) {
        goto err;
    }

    buf[254] = '\0';
    for (;;) {
        i = BIO_gets(bp, buf, 254);

        if (i <= 0) {
            PEMerr(PEM_F_PEM_READ_BIO, PEM_R_NO_START_LINE);
            goto err;
        }

        while ((i >= 0) && (buf[i] <= ' '))
            i--;
        buf[++i] = '\n';
        buf[++i] = '\0';

        if (strncmp(buf, "-----BEGIN ", 11) == 0) {
            i = strlen(&(buf[11]));

            if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
                continue;
            if (!BUF_MEM_grow(nameB, i + 9)) {
                PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            memcpy(nameB->data, &(buf[11]), i - 6);
            nameB->data[i - 6] = '\0';
            break;
        }
    }
    hl = 0;
    if (!BUF_MEM_grow(headerB, 256)) {
        PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    headerB->data[0] = '\0';
    for (;;) {
        i = BIO_gets(bp, buf, 254);
        if (i <= 0)
            break;

        while ((i >= 0) && (buf[i] <= ' '))
            i--;
        buf[++i] = '\n';
        buf[++i] = '\0';

        if (buf[0] == '\n')
            break;
        if (!BUF_MEM_grow(headerB, hl + i + 9)) {
            PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
            goto err;
        }
        if (strncmp(buf, "-----END ", 9) == 0) {
            nohead = 1;
            break;
        }
        memcpy(&(headerB->data[hl]), buf, i);
        headerB->data[hl + i] = '\0';
        hl += i;
    }

    bl = 0;
    if (!BUF_MEM_grow(dataB, 1024)) {
        PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    dataB->data[0] = '\0';
    if (!nohead) {
        for (;;) {
            i = BIO_gets(bp, buf, 254);
            if (i <= 0)
                break;

            while ((i >= 0) && (buf[i] <= ' '))
                i--;
            buf[++i] = '\n';
            buf[++i] = '\0';

            if (i != 65)
                end = 1;
            if (strncmp(buf, "-----END ", 9) == 0)
                break;
            if (i > 65)
                break;
            if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
                PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            memcpy(&(dataB->data[bl]), buf, i);
            dataB->data[bl + i] = '\0';
            bl += i;
            if (end) {
                buf[0] = '\0';
                i = BIO_gets(bp, buf, 254);
                if (i <= 0)
                    break;

                while ((i >= 0) && (buf[i] <= ' '))
                    i--;
                buf[++i] = '\n';
                buf[++i] = '\0';

                break;
            }
        }
    } else {
        tmpB = headerB;
        headerB = dataB;
        dataB = tmpB;
        bl = hl;
    }
    i = strlen(nameB->data);
    if ((strncmp(buf, "-----END ", 9) != 0) ||
        (strncmp(nameB->data, &(buf[9]), i) != 0) ||
        (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
        PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_END_LINE);
        goto err;
    }

    EVP_DecodeInit(ctx);
    i = EVP_DecodeUpdate(ctx,
                         (unsigned char *)dataB->data, &bl,
                         (unsigned char *)dataB->data, bl);
    if (i < 0) {
        PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_BASE64_DECODE);
        goto err;
    }
    i = EVP_DecodeFinal(ctx, (unsigned char *)&(dataB->data[bl]), &k);
    if (i < 0) {
        PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_BASE64_DECODE);
        goto err;
    }
    bl += k;

    if (bl == 0)
        goto err;
    *name = nameB->data;
    *header = headerB->data;
    *data = (unsigned char *)dataB->data;
    *len = bl;
    OPENSSL_free(nameB);
    OPENSSL_free(headerB);
    OPENSSL_free(dataB);
    EVP_ENCODE_CTX_free(ctx);
    return (1);
 err:
    BUF_MEM_free(nameB);
    BUF_MEM_free(headerB);
    BUF_MEM_free(dataB);
    EVP_ENCODE_CTX_free(ctx);
    return (0);
}