155714Skris/* evp_pbe.c */
2296341Sdelphij/*
3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4296341Sdelphij * 1999.
555714Skris */
655714Skris/* ====================================================================
7238405Sjkim * Copyright (c) 1999-2006 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
14296341Sdelphij *    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>
63238405Sjkim#include <openssl/pkcs12.h>
6455714Skris#include <openssl/x509.h>
65238405Sjkim#include "evp_locl.h"
6655714Skris
6755714Skris/* Password based encryption (PBE) functions */
6855714Skris
69238405SjkimDECLARE_STACK_OF(EVP_PBE_CTL)
70238405Sjkimstatic STACK_OF(EVP_PBE_CTL) *pbe_algs;
7155714Skris
7255714Skris/* Setup a cipher context from a PBE algorithm */
7355714Skris
74296341Sdelphijtypedef struct {
75296341Sdelphij    int pbe_type;
76296341Sdelphij    int pbe_nid;
77296341Sdelphij    int cipher_nid;
78296341Sdelphij    int md_nid;
79296341Sdelphij    EVP_PBE_KEYGEN *keygen;
80296341Sdelphij} EVP_PBE_CTL;
8155714Skris
82296341Sdelphijstatic const EVP_PBE_CTL builtin_pbe[] = {
83296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC,
84296341Sdelphij     NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen},
85296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC,
86296341Sdelphij     NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen},
87296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC,
88296341Sdelphij     NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen},
89238405Sjkim
90238405Sjkim#ifndef OPENSSL_NO_HMAC
91296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
92238405Sjkim#endif
93238405Sjkim
94296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4,
95296341Sdelphij     NID_rc4, NID_sha1, PKCS12_PBE_keyivgen},
96296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC4,
97296341Sdelphij     NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen},
98296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
99296341Sdelphij     NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen},
100296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
101296341Sdelphij     NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen},
102296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC2_CBC,
103296341Sdelphij     NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen},
104296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC2_CBC,
105296341Sdelphij     NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen},
106238405Sjkim
107238405Sjkim#ifndef OPENSSL_NO_HMAC
108296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen},
109238405Sjkim#endif
110296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC,
111296341Sdelphij     NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen},
112296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC,
113296341Sdelphij     NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen},
114296341Sdelphij    {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC,
115296341Sdelphij     NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen},
116238405Sjkim
117296341Sdelphij    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0},
118296341Sdelphij    {EVP_PBE_TYPE_PRF, NID_hmacWithMD5, -1, NID_md5, 0},
119296341Sdelphij    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA224, -1, NID_sha224, 0},
120296341Sdelphij    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA256, -1, NID_sha256, 0},
121296341Sdelphij    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA384, -1, NID_sha384, 0},
122296341Sdelphij    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA512, -1, NID_sha512, 0},
123296341Sdelphij    {EVP_PBE_TYPE_PRF, NID_id_HMACGostR3411_94, -1, NID_id_GostR3411_94, 0},
124296341Sdelphij};
125238405Sjkim
126238405Sjkim#ifdef TEST
127238405Sjkimint main(int argc, char **argv)
128296341Sdelphij{
129296341Sdelphij    int i, nid_md, nid_cipher;
130296341Sdelphij    EVP_PBE_CTL *tpbe, *tpbe2;
131296341Sdelphij    /*
132296341Sdelphij     * OpenSSL_add_all_algorithms();
133296341Sdelphij     */
134238405Sjkim
135296341Sdelphij    for (i = 0; i < sizeof(builtin_pbe) / sizeof(EVP_PBE_CTL); i++) {
136296341Sdelphij        tpbe = builtin_pbe + i;
137296341Sdelphij        fprintf(stderr, "%d %d %s ", tpbe->pbe_type, tpbe->pbe_nid,
138296341Sdelphij                OBJ_nid2sn(tpbe->pbe_nid));
139296341Sdelphij        if (EVP_PBE_find(tpbe->pbe_type, tpbe->pbe_nid,
140296341Sdelphij                         &nid_cipher, &nid_md, 0))
141296341Sdelphij            fprintf(stderr, "Found %s %s\n",
142296341Sdelphij                    OBJ_nid2sn(nid_cipher), OBJ_nid2sn(nid_md));
143296341Sdelphij        else
144296341Sdelphij            fprintf(stderr, "Find ERROR!!\n");
145296341Sdelphij    }
146238405Sjkim
147296341Sdelphij    return 0;
148296341Sdelphij}
149238405Sjkim#endif
150238405Sjkim
151160814Ssimonint EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
152296341Sdelphij                       ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
153296341Sdelphij{
154296341Sdelphij    const EVP_CIPHER *cipher;
155296341Sdelphij    const EVP_MD *md;
156296341Sdelphij    int cipher_nid, md_nid;
157296341Sdelphij    EVP_PBE_KEYGEN *keygen;
15855714Skris
159296341Sdelphij    if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
160296341Sdelphij                      &cipher_nid, &md_nid, &keygen)) {
161296341Sdelphij        char obj_tmp[80];
162296341Sdelphij        EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_PBE_ALGORITHM);
163296341Sdelphij        if (!pbe_obj)
164296341Sdelphij            BUF_strlcpy(obj_tmp, "NULL", sizeof obj_tmp);
165296341Sdelphij        else
166296341Sdelphij            i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj);
167296341Sdelphij        ERR_add_error_data(2, "TYPE=", obj_tmp);
168296341Sdelphij        return 0;
169296341Sdelphij    }
17055714Skris
171296341Sdelphij    if (!pass)
172296341Sdelphij        passlen = 0;
173296341Sdelphij    else if (passlen == -1)
174296341Sdelphij        passlen = strlen(pass);
17555714Skris
176296341Sdelphij    if (cipher_nid == -1)
177296341Sdelphij        cipher = NULL;
178296341Sdelphij    else {
179296341Sdelphij        cipher = EVP_get_cipherbynid(cipher_nid);
180296341Sdelphij        if (!cipher) {
181296341Sdelphij            EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_CIPHER);
182296341Sdelphij            return 0;
183296341Sdelphij        }
184296341Sdelphij    }
185238405Sjkim
186296341Sdelphij    if (md_nid == -1)
187296341Sdelphij        md = NULL;
188296341Sdelphij    else {
189296341Sdelphij        md = EVP_get_digestbynid(md_nid);
190296341Sdelphij        if (!md) {
191296341Sdelphij            EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_DIGEST);
192296341Sdelphij            return 0;
193296341Sdelphij        }
194296341Sdelphij    }
195215697Ssimon
196296341Sdelphij    if (!keygen(ctx, pass, passlen, param, cipher, md, en_de)) {
197296341Sdelphij        EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_KEYGEN_FAILURE);
198296341Sdelphij        return 0;
199296341Sdelphij    }
200296341Sdelphij    return 1;
201238405Sjkim}
202238405Sjkim
203238405SjkimDECLARE_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2);
204238405Sjkim
205238405Sjkimstatic int pbe2_cmp(const EVP_PBE_CTL *pbe1, const EVP_PBE_CTL *pbe2)
206296341Sdelphij{
207296341Sdelphij    int ret = pbe1->pbe_type - pbe2->pbe_type;
208296341Sdelphij    if (ret)
209296341Sdelphij        return ret;
210296341Sdelphij    else
211296341Sdelphij        return pbe1->pbe_nid - pbe2->pbe_nid;
212296341Sdelphij}
213238405Sjkim
214238405SjkimIMPLEMENT_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2);
215238405Sjkim
216296341Sdelphijstatic int pbe_cmp(const EVP_PBE_CTL *const *a, const EVP_PBE_CTL *const *b)
217296341Sdelphij{
218296341Sdelphij    int ret = (*a)->pbe_type - (*b)->pbe_type;
219296341Sdelphij    if (ret)
220296341Sdelphij        return ret;
221296341Sdelphij    else
222296341Sdelphij        return (*a)->pbe_nid - (*b)->pbe_nid;
223296341Sdelphij}
224238405Sjkim
225238405Sjkim/* Add a PBE algorithm */
226238405Sjkim
227296341Sdelphijint EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid,
228296341Sdelphij                         int md_nid, EVP_PBE_KEYGEN *keygen)
229296341Sdelphij{
230296341Sdelphij    EVP_PBE_CTL *pbe_tmp;
231296341Sdelphij    if (!pbe_algs)
232296341Sdelphij        pbe_algs = sk_EVP_PBE_CTL_new(pbe_cmp);
233296341Sdelphij    if (!(pbe_tmp = (EVP_PBE_CTL *)OPENSSL_malloc(sizeof(EVP_PBE_CTL)))) {
234296341Sdelphij        EVPerr(EVP_F_EVP_PBE_ALG_ADD_TYPE, ERR_R_MALLOC_FAILURE);
235296341Sdelphij        return 0;
236296341Sdelphij    }
237296341Sdelphij    pbe_tmp->pbe_type = pbe_type;
238296341Sdelphij    pbe_tmp->pbe_nid = pbe_nid;
239296341Sdelphij    pbe_tmp->cipher_nid = cipher_nid;
240296341Sdelphij    pbe_tmp->md_nid = md_nid;
241296341Sdelphij    pbe_tmp->keygen = keygen;
242238405Sjkim
243296341Sdelphij    sk_EVP_PBE_CTL_push(pbe_algs, pbe_tmp);
244296341Sdelphij    return 1;
245296341Sdelphij}
246238405Sjkim
247238405Sjkimint EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
248296341Sdelphij                    EVP_PBE_KEYGEN *keygen)
249296341Sdelphij{
250296341Sdelphij    int cipher_nid, md_nid;
251296341Sdelphij    if (cipher)
252296341Sdelphij        cipher_nid = EVP_CIPHER_nid(cipher);
253296341Sdelphij    else
254296341Sdelphij        cipher_nid = -1;
255296341Sdelphij    if (md)
256296341Sdelphij        md_nid = EVP_MD_type(md);
257296341Sdelphij    else
258296341Sdelphij        md_nid = -1;
259238405Sjkim
260296341Sdelphij    return EVP_PBE_alg_add_type(EVP_PBE_TYPE_OUTER, nid,
261296341Sdelphij                                cipher_nid, md_nid, keygen);
262296341Sdelphij}
263238405Sjkim
264238405Sjkimint EVP_PBE_find(int type, int pbe_nid,
265296341Sdelphij                 int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen)
266296341Sdelphij{
267296341Sdelphij    EVP_PBE_CTL *pbetmp = NULL, pbelu;
268296341Sdelphij    int i;
269296341Sdelphij    if (pbe_nid == NID_undef)
270296341Sdelphij        return 0;
271238405Sjkim
272296341Sdelphij    pbelu.pbe_type = type;
273296341Sdelphij    pbelu.pbe_nid = pbe_nid;
274238405Sjkim
275296341Sdelphij    if (pbe_algs) {
276296341Sdelphij        i = sk_EVP_PBE_CTL_find(pbe_algs, &pbelu);
277296341Sdelphij        if (i != -1)
278296341Sdelphij            pbetmp = sk_EVP_PBE_CTL_value(pbe_algs, i);
279296341Sdelphij    }
280296341Sdelphij    if (pbetmp == NULL) {
281296341Sdelphij        pbetmp = OBJ_bsearch_pbe2(&pbelu, builtin_pbe,
282296341Sdelphij                                  sizeof(builtin_pbe) / sizeof(EVP_PBE_CTL));
283296341Sdelphij    }
284296341Sdelphij    if (pbetmp == NULL)
285296341Sdelphij        return 0;
286296341Sdelphij    if (pcnid)
287296341Sdelphij        *pcnid = pbetmp->cipher_nid;
288296341Sdelphij    if (pmnid)
289296341Sdelphij        *pmnid = pbetmp->md_nid;
290296341Sdelphij    if (pkeygen)
291296341Sdelphij        *pkeygen = pbetmp->keygen;
292296341Sdelphij    return 1;
293296341Sdelphij}
294238405Sjkim
295238405Sjkimstatic void free_evp_pbe_ctl(EVP_PBE_CTL *pbe)
296296341Sdelphij{
297296341Sdelphij    OPENSSL_freeFunc(pbe);
298296341Sdelphij}
299238405Sjkim
30055714Skrisvoid EVP_PBE_cleanup(void)
301296341Sdelphij{
302296341Sdelphij    sk_EVP_PBE_CTL_pop_free(pbe_algs, free_evp_pbe_ctl);
303296341Sdelphij    pbe_algs = NULL;
304296341Sdelphij}
305