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