155714Skris/* evp_pbe.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296465Sdelphij * 1999. 555714Skris */ 655714Skris/* ==================================================================== 755714Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 855714Skris * 955714Skris * Redistribution and use in source and binary forms, with or without 1055714Skris * modification, are permitted provided that the following conditions 1155714Skris * are met: 1255714Skris * 1355714Skris * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 1555714Skris * 1655714Skris * 2. Redistributions in binary form must reproduce the above copyright 1755714Skris * notice, this list of conditions and the following disclaimer in 1855714Skris * the documentation and/or other materials provided with the 1955714Skris * distribution. 2055714Skris * 2155714Skris * 3. All advertising materials mentioning features or use of this 2255714Skris * software must display the following acknowledgment: 2355714Skris * "This product includes software developed by the OpenSSL Project 2455714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2555714Skris * 2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2755714Skris * endorse or promote products derived from this software without 2855714Skris * prior written permission. For written permission, please contact 2955714Skris * licensing@OpenSSL.org. 3055714Skris * 3155714Skris * 5. Products derived from this software may not be called "OpenSSL" 3255714Skris * nor may "OpenSSL" appear in their names without prior written 3355714Skris * permission of the OpenSSL Project. 3455714Skris * 3555714Skris * 6. Redistributions of any form whatsoever must retain the following 3655714Skris * acknowledgment: 3755714Skris * "This product includes software developed by the OpenSSL Project 3855714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3955714Skris * 4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4355714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5255714Skris * ==================================================================== 5355714Skris * 5455714Skris * This product includes cryptographic software written by Eric Young 5555714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5655714Skris * Hudson (tjh@cryptsoft.com). 5755714Skris * 5855714Skris */ 5955714Skris 6055714Skris#include <stdio.h> 61109998Smarkm#include "cryptlib.h" 6255714Skris#include <openssl/evp.h> 6355714Skris#include <openssl/x509.h> 6455714Skris 6555714Skris/* Password based encryption (PBE) functions */ 6655714Skris 6755714Skrisstatic STACK *pbe_algs; 6855714Skris 6955714Skris/* Setup a cipher context from a PBE algorithm */ 7055714Skris 7155714Skristypedef struct { 72296465Sdelphij int pbe_nid; 73296465Sdelphij const EVP_CIPHER *cipher; 74296465Sdelphij const EVP_MD *md; 75296465Sdelphij EVP_PBE_KEYGEN *keygen; 7655714Skris} EVP_PBE_CTL; 7755714Skris 78160814Ssimonint EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, 79296465Sdelphij ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de) 8055714Skris{ 8155714Skris 82296465Sdelphij EVP_PBE_CTL *pbetmp, pbelu; 83296465Sdelphij int i; 84296465Sdelphij pbelu.pbe_nid = OBJ_obj2nid(pbe_obj); 85296465Sdelphij if (pbelu.pbe_nid != NID_undef) 86296465Sdelphij i = sk_find(pbe_algs, (char *)&pbelu); 87296465Sdelphij else 88296465Sdelphij i = -1; 8955714Skris 90296465Sdelphij if (i == -1) { 91296465Sdelphij char obj_tmp[80]; 92296465Sdelphij EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_PBE_ALGORITHM); 93296465Sdelphij if (!pbe_obj) 94296465Sdelphij BUF_strlcpy(obj_tmp, "NULL", sizeof obj_tmp); 95296465Sdelphij else 96296465Sdelphij i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj); 97296465Sdelphij ERR_add_error_data(2, "TYPE=", obj_tmp); 98296465Sdelphij return 0; 99296465Sdelphij } 100296465Sdelphij if (!pass) 101296465Sdelphij passlen = 0; 102296465Sdelphij else if (passlen == -1) 103296465Sdelphij passlen = strlen(pass); 104296465Sdelphij pbetmp = (EVP_PBE_CTL *)sk_value(pbe_algs, i); 105296465Sdelphij i = (*pbetmp->keygen) (ctx, pass, passlen, param, pbetmp->cipher, 106296465Sdelphij pbetmp->md, en_de); 107296465Sdelphij if (!i) { 108296465Sdelphij EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_KEYGEN_FAILURE); 109296465Sdelphij return 0; 110296465Sdelphij } 111296465Sdelphij return 1; 11255714Skris} 11355714Skris 114296465Sdelphijstatic int pbe_cmp(const char *const *a, const char *const *b) 11555714Skris{ 116296465Sdelphij const EVP_PBE_CTL *const *pbe1 = (const EVP_PBE_CTL *const *)a, 117296465Sdelphij *const *pbe2 = (const EVP_PBE_CTL *const *)b; 118296465Sdelphij return ((*pbe1)->pbe_nid - (*pbe2)->pbe_nid); 11955714Skris} 12055714Skris 12155714Skris/* Add a PBE algorithm */ 12255714Skris 123109998Smarkmint EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, 124296465Sdelphij EVP_PBE_KEYGEN *keygen) 12555714Skris{ 126296465Sdelphij EVP_PBE_CTL *pbe_tmp = NULL, pbelu; 127296465Sdelphij int i; 128296465Sdelphij if (!pbe_algs) { 129296465Sdelphij pbe_algs = sk_new(pbe_cmp); 130296465Sdelphij if (!pbe_algs) { 131296465Sdelphij EVPerr(EVP_F_EVP_PBE_ALG_ADD, ERR_R_MALLOC_FAILURE); 132296465Sdelphij return 0; 133296465Sdelphij } 134296465Sdelphij } else { 135296465Sdelphij /* Check if already present */ 136296465Sdelphij pbelu.pbe_nid = nid; 137296465Sdelphij i = sk_find(pbe_algs, (char *)&pbelu); 138296465Sdelphij if (i >= 0) { 139296465Sdelphij pbe_tmp = (EVP_PBE_CTL *)sk_value(pbe_algs, i); 140296465Sdelphij /* If everything identical leave alone */ 141296465Sdelphij if (pbe_tmp->cipher == cipher 142296465Sdelphij && pbe_tmp->md == md && pbe_tmp->keygen == keygen) 143296465Sdelphij return 1; 144296465Sdelphij } 145296465Sdelphij } 146215697Ssimon 147296465Sdelphij if (!pbe_tmp) { 148296465Sdelphij pbe_tmp = OPENSSL_malloc(sizeof(EVP_PBE_CTL)); 149296465Sdelphij if (!pbe_tmp) { 150296465Sdelphij EVPerr(EVP_F_EVP_PBE_ALG_ADD, ERR_R_MALLOC_FAILURE); 151296465Sdelphij return 0; 152296465Sdelphij } 153296465Sdelphij /* If adding a new PBE, set nid, append and sort */ 154296465Sdelphij pbe_tmp->pbe_nid = nid; 155296465Sdelphij sk_push(pbe_algs, (char *)pbe_tmp); 156296465Sdelphij sk_sort(pbe_algs); 157296465Sdelphij } 158296465Sdelphij 159296465Sdelphij pbe_tmp->cipher = cipher; 160296465Sdelphij pbe_tmp->md = md; 161296465Sdelphij pbe_tmp->keygen = keygen; 162296465Sdelphij return 1; 16355714Skris} 16455714Skris 16555714Skrisvoid EVP_PBE_cleanup(void) 16655714Skris{ 167296465Sdelphij sk_pop_free(pbe_algs, OPENSSL_freeFunc); 168296465Sdelphij pbe_algs = NULL; 16955714Skris} 170