crypto/pkcs12: facilitate accessing data with non-interoperable password.
[openssl.git] / crypto / pkcs12 / p12_crpt.c
1 /*
2  * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/pkcs12.h>
13
14 /* PKCS#12 PBE algorithms now in static table */
15
16 void PKCS12_PBE_add(void)
17 {
18 }
19
20 #undef PKCS12_key_gen
21 /*
22  * See p12_multi.c:PKCS12_verify_mac() for details...
23  */
24 extern int (*PKCS12_key_gen)(const char *pass, int passlen,
25                              unsigned char *salt, int slen,
26                              int id, int iter, int n,
27                              unsigned char *out,
28                              const EVP_MD *md_type);
29
30 int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
31                         ASN1_TYPE *param, const EVP_CIPHER *cipher,
32                         const EVP_MD *md, int en_de)
33 {
34     PBEPARAM *pbe;
35     int saltlen, iter, ret;
36     unsigned char *salt;
37     unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
38     int (*pkcs12_key_gen)(const char *pass, int passlen,
39                           unsigned char *salt, int slen,
40                           int id, int iter, int n,
41                           unsigned char *out,
42                           const EVP_MD *md_type);
43
44     if (PKCS12_key_gen == NULL || en_de)
45         /*
46          * Default to UTF-8, but force it in encrypt case.
47          */
48         pkcs12_key_gen = PKCS12_key_gen_utf8;
49     else
50         pkcs12_key_gen = PKCS12_key_gen;
51
52     if (cipher == NULL)
53         return 0;
54
55     /* Extract useful info from parameter */
56
57     pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), param);
58     if (pbe == NULL) {
59         PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_DECODE_ERROR);
60         return 0;
61     }
62
63     if (!pbe->iter)
64         iter = 1;
65     else
66         iter = ASN1_INTEGER_get(pbe->iter);
67     salt = pbe->salt->data;
68     saltlen = pbe->salt->length;
69     if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_KEY_ID,
70                            iter, EVP_CIPHER_key_length(cipher), key, md)) {
71         PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_KEY_GEN_ERROR);
72         PBEPARAM_free(pbe);
73         return 0;
74     }
75     if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_IV_ID,
76                            iter, EVP_CIPHER_iv_length(cipher), iv, md)) {
77         PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_IV_GEN_ERROR);
78         PBEPARAM_free(pbe);
79         return 0;
80     }
81     PBEPARAM_free(pbe);
82     ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de);
83     OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
84     OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
85     return ret;
86 }