evp_pbe.c revision 296465
1/* evp_pbe.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 1999. 5 */ 6/* ==================================================================== 7 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdio.h> 61#include "cryptlib.h" 62#include <openssl/evp.h> 63#include <openssl/x509.h> 64 65/* Password based encryption (PBE) functions */ 66 67static STACK *pbe_algs; 68 69/* Setup a cipher context from a PBE algorithm */ 70 71typedef struct { 72 int pbe_nid; 73 const EVP_CIPHER *cipher; 74 const EVP_MD *md; 75 EVP_PBE_KEYGEN *keygen; 76} EVP_PBE_CTL; 77 78int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, 79 ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de) 80{ 81 82 EVP_PBE_CTL *pbetmp, pbelu; 83 int i; 84 pbelu.pbe_nid = OBJ_obj2nid(pbe_obj); 85 if (pbelu.pbe_nid != NID_undef) 86 i = sk_find(pbe_algs, (char *)&pbelu); 87 else 88 i = -1; 89 90 if (i == -1) { 91 char obj_tmp[80]; 92 EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_PBE_ALGORITHM); 93 if (!pbe_obj) 94 BUF_strlcpy(obj_tmp, "NULL", sizeof obj_tmp); 95 else 96 i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj); 97 ERR_add_error_data(2, "TYPE=", obj_tmp); 98 return 0; 99 } 100 if (!pass) 101 passlen = 0; 102 else if (passlen == -1) 103 passlen = strlen(pass); 104 pbetmp = (EVP_PBE_CTL *)sk_value(pbe_algs, i); 105 i = (*pbetmp->keygen) (ctx, pass, passlen, param, pbetmp->cipher, 106 pbetmp->md, en_de); 107 if (!i) { 108 EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_KEYGEN_FAILURE); 109 return 0; 110 } 111 return 1; 112} 113 114static int pbe_cmp(const char *const *a, const char *const *b) 115{ 116 const EVP_PBE_CTL *const *pbe1 = (const EVP_PBE_CTL *const *)a, 117 *const *pbe2 = (const EVP_PBE_CTL *const *)b; 118 return ((*pbe1)->pbe_nid - (*pbe2)->pbe_nid); 119} 120 121/* Add a PBE algorithm */ 122 123int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, 124 EVP_PBE_KEYGEN *keygen) 125{ 126 EVP_PBE_CTL *pbe_tmp = NULL, pbelu; 127 int i; 128 if (!pbe_algs) { 129 pbe_algs = sk_new(pbe_cmp); 130 if (!pbe_algs) { 131 EVPerr(EVP_F_EVP_PBE_ALG_ADD, ERR_R_MALLOC_FAILURE); 132 return 0; 133 } 134 } else { 135 /* Check if already present */ 136 pbelu.pbe_nid = nid; 137 i = sk_find(pbe_algs, (char *)&pbelu); 138 if (i >= 0) { 139 pbe_tmp = (EVP_PBE_CTL *)sk_value(pbe_algs, i); 140 /* If everything identical leave alone */ 141 if (pbe_tmp->cipher == cipher 142 && pbe_tmp->md == md && pbe_tmp->keygen == keygen) 143 return 1; 144 } 145 } 146 147 if (!pbe_tmp) { 148 pbe_tmp = OPENSSL_malloc(sizeof(EVP_PBE_CTL)); 149 if (!pbe_tmp) { 150 EVPerr(EVP_F_EVP_PBE_ALG_ADD, ERR_R_MALLOC_FAILURE); 151 return 0; 152 } 153 /* If adding a new PBE, set nid, append and sort */ 154 pbe_tmp->pbe_nid = nid; 155 sk_push(pbe_algs, (char *)pbe_tmp); 156 sk_sort(pbe_algs); 157 } 158 159 pbe_tmp->cipher = cipher; 160 pbe_tmp->md = md; 161 pbe_tmp->keygen = keygen; 162 return 1; 163} 164 165void EVP_PBE_cleanup(void) 166{ 167 sk_pop_free(pbe_algs, OPENSSL_freeFunc); 168 pbe_algs = NULL; 169} 170