diff options
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/pem/pem_lib.c')
-rw-r--r-- | Cryptlib/OpenSSL/crypto/pem/pem_lib.c | 422 |
1 files changed, 218 insertions, 204 deletions
diff --git a/Cryptlib/OpenSSL/crypto/pem/pem_lib.c b/Cryptlib/OpenSSL/crypto/pem/pem_lib.c index 2792593c..56c77b1f 100644 --- a/Cryptlib/OpenSSL/crypto/pem/pem_lib.c +++ b/Cryptlib/OpenSSL/crypto/pem/pem_lib.c @@ -1,16 +1,64 @@ -/* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +/* crypto/pem/pem_lib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ #include <stdio.h> #include <ctype.h> -#include <string.h> -#include "internal/cryptlib.h" +#include "cryptlib.h" #include <openssl/buffer.h> #include <openssl/objects.h> #include <openssl/evp.h> @@ -18,9 +66,15 @@ #include <openssl/x509.h> #include <openssl/pem.h> #include <openssl/pkcs12.h> -#include "internal/asn1_int.h" -#include <openssl/des.h> -#include <openssl/engine.h> +#include "asn1_locl.h" +#ifndef OPENSSL_NO_DES +# include <openssl/des.h> +#endif +#ifndef OPENSSL_NO_ENGINE +# include <openssl/engine.h> +#endif + +const char PEM_version[] = "PEM" OPENSSL_VERSION_PTEXT; #define MIN_LENGTH 4 @@ -30,24 +84,22 @@ int pem_check_suffix(const char *pem_str, const char *suffix); int PEM_def_callback(char *buf, int num, int w, void *key) { -#if defined(OPENSSL_NO_STDIO) || defined(OPENSSL_NO_UI) - int i; +#if defined(OPENSSL_NO_FP_API) || defined(OPENSSL_NO_UI) + /* + * We should not ever call the default callback routine from windows. + */ + PEMerr(PEM_F_PEM_DEF_CALLBACK, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return (-1); #else int i, j; const char *prompt; -#endif - if (key) { i = strlen(key); i = (i > num) ? num : i; memcpy(buf, key, i); - return i; + return (i); } -#if defined(OPENSSL_NO_STDIO) || defined(OPENSSL_NO_UI) - PEMerr(PEM_F_PEM_DEF_CALLBACK, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return -1; -#else prompt = EVP_get_pw_prompt(); if (prompt == NULL) prompt = "Enter PEM pass phrase:"; @@ -63,7 +115,7 @@ int PEM_def_callback(char *buf, int num, int w, void *key) if (i != 0) { PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD); memset(buf, 0, (unsigned int)num); - return -1; + return (-1); } j = strlen(buf); if (min_len && j < min_len) { @@ -73,7 +125,7 @@ int PEM_def_callback(char *buf, int num, int w, void *key) } else break; } - return j; + return (j); #endif } @@ -90,9 +142,9 @@ void PEM_proc_type(char *buf, int type) else str = "BAD-TYPE"; - OPENSSL_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE); - OPENSSL_strlcat(buf, str, PEM_BUFSIZE); - OPENSSL_strlcat(buf, "\n", PEM_BUFSIZE); + BUF_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE); + BUF_strlcat(buf, str, PEM_BUFSIZE); + BUF_strlcat(buf, "\n", PEM_BUFSIZE); } void PEM_dek_info(char *buf, const char *type, int len, char *str) @@ -101,9 +153,9 @@ void PEM_dek_info(char *buf, const char *type, int len, char *str) long i; int j; - OPENSSL_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE); - OPENSSL_strlcat(buf, type, PEM_BUFSIZE); - OPENSSL_strlcat(buf, ",", PEM_BUFSIZE); + BUF_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE); + BUF_strlcat(buf, type, PEM_BUFSIZE); + BUF_strlcat(buf, ",", PEM_BUFSIZE); j = strlen(buf); if (j + (len * 2) + 1 > PEM_BUFSIZE) return; @@ -115,7 +167,7 @@ void PEM_dek_info(char *buf, const char *type, int len, char *str) buf[j + i * 2 + 1] = '\0'; } -#ifndef OPENSSL_NO_STDIO +#ifndef OPENSSL_NO_FP_API void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, pem_password_cb *cb, void *u) { @@ -136,22 +188,22 @@ void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, static int check_pem(const char *nm, const char *name) { /* Normal matching nm and name */ - if (strcmp(nm, name) == 0) + if (!strcmp(nm, name)) return 1; /* Make PEM_STRING_EVP_PKEY match any private key */ - if (strcmp(name, PEM_STRING_EVP_PKEY) == 0) { + if (!strcmp(name, PEM_STRING_EVP_PKEY)) { int slen; const EVP_PKEY_ASN1_METHOD *ameth; - if (strcmp(nm, PEM_STRING_PKCS8) == 0) + if (!strcmp(nm, PEM_STRING_PKCS8)) return 1; - if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) + if (!strcmp(nm, PEM_STRING_PKCS8INF)) return 1; slen = pem_check_suffix(nm, "PRIVATE KEY"); if (slen > 0) { /* - * NB: ENGINE implementations won't contain a deprecated old + * NB: ENGINE implementations wont contain a deprecated old * private key decode function so don't look for them. */ ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); @@ -161,7 +213,7 @@ static int check_pem(const char *nm, const char *name) return 0; } - if (strcmp(name, PEM_STRING_PARAMETERS) == 0) { + if (!strcmp(name, PEM_STRING_PARAMETERS)) { int slen; const EVP_PKEY_ASN1_METHOD *ameth; slen = pem_check_suffix(nm, "PARAMETERS"); @@ -175,7 +227,8 @@ static int check_pem(const char *nm, const char *name) else r = 0; #ifndef OPENSSL_NO_ENGINE - ENGINE_finish(e); + if (e) + ENGINE_finish(e); #endif return r; } @@ -183,45 +236,41 @@ static int check_pem(const char *nm, const char *name) return 0; } /* If reading DH parameters handle X9.42 DH format too */ - if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0 - && strcmp(name, PEM_STRING_DHPARAMS) == 0) + if (!strcmp(nm, PEM_STRING_DHXPARAMS) && + !strcmp(name, PEM_STRING_DHPARAMS)) return 1; /* Permit older strings */ - if (strcmp(nm, PEM_STRING_X509_OLD) == 0 - && strcmp(name, PEM_STRING_X509) == 0) + if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) return 1; - if (strcmp(nm, PEM_STRING_X509_REQ_OLD) == 0 - && strcmp(name, PEM_STRING_X509_REQ) == 0) + if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) && + !strcmp(name, PEM_STRING_X509_REQ)) return 1; /* Allow normal certs to be read as trusted certs */ - if (strcmp(nm, PEM_STRING_X509) == 0 - && strcmp(name, PEM_STRING_X509_TRUSTED) == 0) + if (!strcmp(nm, PEM_STRING_X509) && + !strcmp(name, PEM_STRING_X509_TRUSTED)) return 1; - if (strcmp(nm, PEM_STRING_X509_OLD) == 0 - && strcmp(name, PEM_STRING_X509_TRUSTED) == 0) + if (!strcmp(nm, PEM_STRING_X509_OLD) && + !strcmp(name, PEM_STRING_X509_TRUSTED)) return 1; /* Some CAs use PKCS#7 with CERTIFICATE headers */ - if (strcmp(nm, PEM_STRING_X509) == 0 - && strcmp(name, PEM_STRING_PKCS7) == 0) + if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) return 1; - if (strcmp(nm, PEM_STRING_PKCS7_SIGNED) == 0 - && strcmp(name, PEM_STRING_PKCS7) == 0) + if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && + !strcmp(name, PEM_STRING_PKCS7)) return 1; #ifndef OPENSSL_NO_CMS - if (strcmp(nm, PEM_STRING_X509) == 0 - && strcmp(name, PEM_STRING_CMS) == 0) + if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS)) return 1; /* Allow CMS to be read from PKCS#7 headers */ - if (strcmp(nm, PEM_STRING_PKCS7) == 0 - && strcmp(name, PEM_STRING_CMS) == 0) + if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS)) return 1; #endif @@ -272,7 +321,7 @@ int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, return ret; } -#ifndef OPENSSL_NO_STDIO +#ifndef OPENSSL_NO_FP_API int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, void *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *callback, void *u) @@ -295,8 +344,8 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *callback, void *u) { - EVP_CIPHER_CTX *ctx = NULL; - int dsize = 0, i = 0, j = 0, ret = 0; + EVP_CIPHER_CTX ctx; + int dsize = 0, i, j, ret = 0; unsigned char *p, *data = NULL; const char *objstr = NULL; char buf[PEM_BUFSIZE]; @@ -318,7 +367,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, } /* dzise + 8 bytes are needed */ /* actually it needs the cipher block size extra... */ - data = OPENSSL_malloc((unsigned int)dsize + 20); + data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20); if (data == NULL) { PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_MALLOC_FAILURE); goto err; @@ -343,8 +392,8 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, kstr = (unsigned char *)buf; } RAND_add(data, i, 0); /* put in the RSA key. */ - OPENSSL_assert(EVP_CIPHER_iv_length(enc) <= (int)sizeof(iv)); - if (RAND_bytes(iv, EVP_CIPHER_iv_length(enc)) <= 0) /* Generate a salt */ + OPENSSL_assert(enc->iv_len <= (int)sizeof(iv)); + if (RAND_bytes(iv, enc->iv_len) <= 0) /* Generate a salt */ goto err; /* * The 'iv' is used as the iv and as a salt. It is NOT taken from @@ -356,20 +405,21 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf, PEM_BUFSIZE); - OPENSSL_assert(strlen(objstr) + 23 + 2 * EVP_CIPHER_iv_length(enc) + 13 - <= sizeof buf); + OPENSSL_assert(strlen(objstr) + 23 + 2 * enc->iv_len + 13 <= + sizeof buf); buf[0] = '\0'; PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); - PEM_dek_info(buf, objstr, EVP_CIPHER_iv_length(enc), (char *)iv); + PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv); /* k=strlen(buf); */ + EVP_CIPHER_CTX_init(&ctx); ret = 1; - if ((ctx = EVP_CIPHER_CTX_new()) == NULL - || !EVP_EncryptInit_ex(ctx, enc, NULL, key, iv) - || !EVP_EncryptUpdate(ctx, data, &j, data, i) - || !EVP_EncryptFinal_ex(ctx, &(data[j]), &i)) + if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) + || !EVP_EncryptUpdate(&ctx, data, &j, data, i) + || !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i)) ret = 0; + EVP_CIPHER_CTX_cleanup(&ctx); if (ret == 0) goto err; i += j; @@ -383,162 +433,127 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, err: OPENSSL_cleanse(key, sizeof(key)); OPENSSL_cleanse(iv, sizeof(iv)); - EVP_CIPHER_CTX_free(ctx); + OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); OPENSSL_cleanse(buf, PEM_BUFSIZE); - OPENSSL_clear_free(data, (unsigned int)dsize); + if (data != NULL) { + OPENSSL_cleanse(data, (unsigned int)dsize); + OPENSSL_free(data); + } return (ret); } int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, pem_password_cb *callback, void *u) { - int ok; - int keylen; - long len = *plen; - int ilen = (int) len; /* EVP_DecryptUpdate etc. take int lengths */ - EVP_CIPHER_CTX *ctx; + int i = 0, j, o, klen; + long len; + EVP_CIPHER_CTX ctx; unsigned char key[EVP_MAX_KEY_LENGTH]; char buf[PEM_BUFSIZE]; -#if LONG_MAX > INT_MAX - /* Check that we did not truncate the length */ - if (len > INT_MAX) { - PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_HEADER_TOO_LONG); - return 0; - } -#endif + len = *plen; if (cipher->cipher == NULL) - return 1; + return (1); if (callback == NULL) - keylen = PEM_def_callback(buf, PEM_BUFSIZE, 0, u); + klen = PEM_def_callback(buf, PEM_BUFSIZE, 0, u); else - keylen = callback(buf, PEM_BUFSIZE, 0, u); - if (keylen <= 0) { + klen = callback(buf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_PASSWORD_READ); - return 0; + return (0); } #ifdef CHARSET_EBCDIC /* Convert the pass phrase from EBCDIC */ - ebcdic2ascii(buf, buf, keylen); + ebcdic2ascii(buf, buf, klen); #endif if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]), - (unsigned char *)buf, keylen, 1, key, NULL)) - return 0; - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) + (unsigned char *)buf, klen, 1, key, NULL)) return 0; - ok = EVP_DecryptInit_ex(ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); - if (ok) - ok = EVP_DecryptUpdate(ctx, data, &ilen, data, ilen); - if (ok) { - /* Squirrel away the length of data decrypted so far. */ - *plen = ilen; - ok = EVP_DecryptFinal_ex(ctx, &(data[ilen]), &ilen); - } - if (ok) - *plen += ilen; - else - PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT); - - EVP_CIPHER_CTX_free(ctx); + j = (int)len; + EVP_CIPHER_CTX_init(&ctx); + o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); + if (o) + o = EVP_DecryptUpdate(&ctx, data, &i, data, j); + if (o) + o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j); + EVP_CIPHER_CTX_cleanup(&ctx); OPENSSL_cleanse((char *)buf, sizeof(buf)); OPENSSL_cleanse((char *)key, sizeof(key)); - return ok; + if (o) + j += i; + else { + PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT); + return (0); + } + *plen = j; + return (1); } -/* - * This implements a very limited PEM header parser that does not support the - * full grammar of rfc1421. In particular, folded headers are not supported, - * nor is additional whitespace. - * - * A robust implementation would make use of a library that turns the headers - * into a BIO from which one folded line is read at a time, and is then split - * into a header label and content. We would then parse the content of the - * headers we care about. This is overkill for just this limited use-case, but - * presumably we also parse rfc822-style headers for S/MIME, so a common - * abstraction might well be more generally useful. - */ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) { - static const char ProcType[] = "Proc-Type:"; - static const char ENCRYPTED[] = "ENCRYPTED"; - static const char DEKInfo[] = "DEK-Info:"; const EVP_CIPHER *enc = NULL; - int ivlen; - char *dekinfostart, c; + char *p, c; + char **header_pp = &header; cipher->cipher = NULL; if ((header == NULL) || (*header == '\0') || (*header == '\n')) - return 1; - - if (strncmp(header, ProcType, sizeof(ProcType)-1) != 0) { + return (1); + if (strncmp(header, "Proc-Type: ", 11) != 0) { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_PROC_TYPE); - return 0; + return (0); } - header += sizeof(ProcType)-1; - header += strspn(header, " \t"); - - if (*header++ != '4' || *header++ != ',') - return 0; - header += strspn(header, " \t"); - - /* We expect "ENCRYPTED" followed by optional white-space + line break */ - if (strncmp(header, ENCRYPTED, sizeof(ENCRYPTED)-1) != 0 || - strspn(header+sizeof(ENCRYPTED)-1, " \t\r\n") == 0) { + header += 11; + if (*header != '4') + return (0); + header++; + if (*header != ',') + return (0); + header++; + if (strncmp(header, "ENCRYPTED", 9) != 0) { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_ENCRYPTED); - return 0; + return (0); } - header += sizeof(ENCRYPTED)-1; - header += strspn(header, " \t\r"); - if (*header++ != '\n') { + for (; (*header != '\n') && (*header != '\0'); header++) ; + if (*header == '\0') { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_SHORT_HEADER); - return 0; + return (0); } - - /*- - * https://tools.ietf.org/html/rfc1421#section-4.6.1.3 - * We expect "DEK-Info: algo[,hex-parameters]" - */ - if (strncmp(header, DEKInfo, sizeof(DEKInfo)-1) != 0) { + header++; + if (strncmp(header, "DEK-Info: ", 10) != 0) { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_DEK_INFO); - return 0; + return (0); } - header += sizeof(DEKInfo)-1; - header += strspn(header, " \t"); + header += 10; - /* - * DEK-INFO is a comma-separated combination of algorithm name and optional - * parameters. - */ - dekinfostart = header; - header += strcspn(header, " \t,"); - c = *header; + p = header; + for (;;) { + c = *header; +#ifndef CHARSET_EBCDIC + if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') || + ((c >= '0') && (c <= '9')))) + break; +#else + if (!(isupper(c) || (c == '-') || isdigit(c))) + break; +#endif + header++; + } *header = '\0'; - cipher->cipher = enc = EVP_get_cipherbyname(dekinfostart); + cipher->cipher = enc = EVP_get_cipherbyname(p); *header = c; - header += strspn(header, " \t"); + header++; if (enc == NULL) { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_UNSUPPORTED_ENCRYPTION); - return 0; - } - ivlen = EVP_CIPHER_iv_length(enc); - if (ivlen > 0 && *header++ != ',') { - PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_MISSING_DEK_IV); - return 0; - } else if (ivlen == 0 && *header == ',') { - PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_UNEXPECTED_DEK_IV); - return 0; + return (0); } + if (!load_iv(header_pp, &(cipher->iv[0]), enc->iv_len)) + return (0); - if (!load_iv(&header, cipher->iv, EVP_CIPHER_iv_length(enc))) - return 0; - - return 1; + return (1); } static int load_iv(char **fromp, unsigned char *to, int num) @@ -551,8 +566,13 @@ static int load_iv(char **fromp, unsigned char *to, int num) to[i] = 0; num *= 2; for (i = 0; i < num; i++) { - v = OPENSSL_hexchar2int(*from); - if (v < 0) { + if ((*from >= '0') && (*from <= '9')) + v = *from - '0'; + else if ((*from >= 'A') && (*from <= 'F')) + v = *from - 'A' + 10; + else if ((*from >= 'a') && (*from <= 'f')) + v = *from - 'a' + 10; + else { PEMerr(PEM_F_LOAD_IV, PEM_R_BAD_IV_CHARS); return (0); } @@ -564,7 +584,7 @@ static int load_iv(char **fromp, unsigned char *to, int num) return (1); } -#ifndef OPENSSL_NO_STDIO +#ifndef OPENSSL_NO_FP_API int PEM_write(FILE *fp, const char *name, const char *header, const unsigned char *data, long len) { @@ -587,15 +607,10 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header, { int nlen, n, i, j, outl; unsigned char *buf = NULL; - EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); + EVP_ENCODE_CTX ctx; int reason = ERR_R_BUF_LIB; - if (ctx == NULL) { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - - EVP_EncodeInit(ctx); + EVP_EncodeInit(&ctx); nlen = strlen(name); if ((BIO_write(bp, "-----BEGIN ", 11) != 11) || @@ -618,32 +633,34 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header, 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; + EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n); if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) goto err; i += outl; len -= n; j += n; } - EVP_EncodeFinal(ctx, buf, &outl); + EVP_EncodeFinal(&ctx, buf, &outl); if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) goto err; + OPENSSL_cleanse(buf, PEM_BUFSIZE * 8); + OPENSSL_free(buf); + buf = NULL; 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); + if (buf) { + OPENSSL_cleanse(buf, PEM_BUFSIZE * 8); + OPENSSL_free(buf); + } PEMerr(PEM_F_PEM_WRITE_BIO, reason); return (0); } -#ifndef OPENSSL_NO_STDIO +#ifndef OPENSSL_NO_FP_API int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, long *len) { @@ -664,23 +681,22 @@ int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, long *len) { - EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); + EVP_ENCODE_CTX ctx; 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_MEM_free(nameB); + BUF_MEM_free(headerB); + BUF_MEM_free(dataB); + PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE); + return (0); } buf[254] = '\0'; @@ -800,15 +816,15 @@ int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, goto err; } - EVP_DecodeInit(ctx); - i = EVP_DecodeUpdate(ctx, + 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); + 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; @@ -824,13 +840,11 @@ int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, 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); } |