16f9291ceSJung-uk Kim /*
2b077aed3SPierre Pronchery  * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
374664626SKris Kennaway  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
874664626SKris Kennaway  */
974664626SKris Kennaway 
1074664626SKris Kennaway #include <stdio.h>
11e71b7053SJung-uk Kim #include "internal/cryptlib.h"
1274664626SKris Kennaway #include <openssl/pkcs12.h>
13b077aed3SPierre Pronchery #include <openssl/trace.h>
1474664626SKris Kennaway 
156f9291ceSJung-uk Kim /*
166f9291ceSJung-uk Kim  * Encrypt/Decrypt a buffer based on password and algor, result in a
17ddd58736SKris Kennaway  * OPENSSL_malloc'ed buffer
1874664626SKris Kennaway  */
PKCS12_pbe_crypt_ex(const X509_ALGOR * algor,const char * pass,int passlen,const unsigned char * in,int inlen,unsigned char ** data,int * datalen,int en_de,OSSL_LIB_CTX * libctx,const char * propq)19b077aed3SPierre Pronchery unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
20e71b7053SJung-uk Kim                                    const char *pass, int passlen,
21e71b7053SJung-uk Kim                                    const unsigned char *in, int inlen,
22b077aed3SPierre Pronchery                                    unsigned char **data, int *datalen, int en_de,
23b077aed3SPierre Pronchery                                    OSSL_LIB_CTX *libctx, const char *propq)
2474664626SKris Kennaway {
25e71b7053SJung-uk Kim     unsigned char *out = NULL;
2674664626SKris Kennaway     int outlen, i;
27e71b7053SJung-uk Kim     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
28b077aed3SPierre Pronchery     int max_out_len, mac_len = 0;
2974664626SKris Kennaway 
30e71b7053SJung-uk Kim     if (ctx == NULL) {
31b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
325c87c606SMark Murray         goto err;
3374664626SKris Kennaway     }
3474664626SKris Kennaway 
35b077aed3SPierre Pronchery     /* Process data */
36b077aed3SPierre Pronchery     if (!EVP_PBE_CipherInit_ex(algor->algorithm, pass, passlen,
37b077aed3SPierre Pronchery                                algor->parameter, ctx, en_de, libctx, propq))
38b077aed3SPierre Pronchery         goto err;
39b077aed3SPierre Pronchery 
40b077aed3SPierre Pronchery     /*
41b077aed3SPierre Pronchery      * GOST algorithm specifics:
42b077aed3SPierre Pronchery      * OMAC algorithm calculate and encrypt MAC of the encrypted objects
43b077aed3SPierre Pronchery      * It's appended to encrypted text on encrypting
44b077aed3SPierre Pronchery      * MAC should be processed on decrypting separately from plain text
45b077aed3SPierre Pronchery      */
46b077aed3SPierre Pronchery     max_out_len = inlen + EVP_CIPHER_CTX_get_block_size(ctx);
47b077aed3SPierre Pronchery     if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
48b077aed3SPierre Pronchery                 & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
49b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) < 0) {
50b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
51e71b7053SJung-uk Kim             goto err;
52e71b7053SJung-uk Kim         }
53e71b7053SJung-uk Kim 
54b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
55b077aed3SPierre Pronchery             max_out_len += mac_len;
56b077aed3SPierre Pronchery         } else {
57b077aed3SPierre Pronchery             if (inlen < mac_len) {
58b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNSUPPORTED_PKCS12_MODE);
59b077aed3SPierre Pronchery                 goto err;
60b077aed3SPierre Pronchery             }
61b077aed3SPierre Pronchery             inlen -= mac_len;
62b077aed3SPierre Pronchery             if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
63b077aed3SPierre Pronchery                                     (int)mac_len, (unsigned char *)in+inlen) < 0) {
64b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
65b077aed3SPierre Pronchery                 goto err;
66b077aed3SPierre Pronchery             }
67b077aed3SPierre Pronchery         }
68b077aed3SPierre Pronchery     }
69b077aed3SPierre Pronchery 
70b077aed3SPierre Pronchery     if ((out = OPENSSL_malloc(max_out_len)) == NULL) {
71b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
72e71b7053SJung-uk Kim         goto err;
73e71b7053SJung-uk Kim     }
74e71b7053SJung-uk Kim 
75e71b7053SJung-uk Kim     if (!EVP_CipherUpdate(ctx, out, &i, in, inlen)) {
761f13597dSJung-uk Kim         OPENSSL_free(out);
771f13597dSJung-uk Kim         out = NULL;
78b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PKCS12, ERR_R_EVP_LIB);
791f13597dSJung-uk Kim         goto err;
801f13597dSJung-uk Kim     }
811f13597dSJung-uk Kim 
8274664626SKris Kennaway     outlen = i;
83e71b7053SJung-uk Kim     if (!EVP_CipherFinal_ex(ctx, out + i, &i)) {
84ddd58736SKris Kennaway         OPENSSL_free(out);
855c87c606SMark Murray         out = NULL;
86b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_PKCS12, PKCS12_R_PKCS12_CIPHERFINAL_ERROR,
87b077aed3SPierre Pronchery                        passlen == 0 ? "empty password"
88b077aed3SPierre Pronchery                        : "maybe wrong password");
895c87c606SMark Murray         goto err;
9074664626SKris Kennaway     }
9174664626SKris Kennaway     outlen += i;
92b077aed3SPierre Pronchery     if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
93b077aed3SPierre Pronchery                 & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
94b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
95b077aed3SPierre Pronchery             if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG,
96b077aed3SPierre Pronchery                 (int)mac_len, out+outlen) < 0) {
97b077aed3SPierre Pronchery                 OPENSSL_free(out);
98b077aed3SPierre Pronchery                 out = NULL;
99b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR);
100b077aed3SPierre Pronchery                 goto err;
101b077aed3SPierre Pronchery             }
102b077aed3SPierre Pronchery             outlen += mac_len;
103b077aed3SPierre Pronchery         }
104b077aed3SPierre Pronchery     }
1056f9291ceSJung-uk Kim     if (datalen)
1066f9291ceSJung-uk Kim         *datalen = outlen;
1076f9291ceSJung-uk Kim     if (data)
1086f9291ceSJung-uk Kim         *data = out;
1095c87c606SMark Murray  err:
110e71b7053SJung-uk Kim     EVP_CIPHER_CTX_free(ctx);
11174664626SKris Kennaway     return out;
11274664626SKris Kennaway 
11374664626SKris Kennaway }
11474664626SKris Kennaway 
PKCS12_pbe_crypt(const X509_ALGOR * algor,const char * pass,int passlen,const unsigned char * in,int inlen,unsigned char ** data,int * datalen,int en_de)115b077aed3SPierre Pronchery unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
116b077aed3SPierre Pronchery                                 const char *pass, int passlen,
117b077aed3SPierre Pronchery                                 const unsigned char *in, int inlen,
118b077aed3SPierre Pronchery                                 unsigned char **data, int *datalen, int en_de)
119b077aed3SPierre Pronchery {
120b077aed3SPierre Pronchery     return PKCS12_pbe_crypt_ex(algor, pass, passlen, in, inlen, data, datalen,
121b077aed3SPierre Pronchery                                en_de, NULL, NULL);
122b077aed3SPierre Pronchery }
123b077aed3SPierre Pronchery 
1246f9291ceSJung-uk Kim /*
1256f9291ceSJung-uk Kim  * Decrypt an OCTET STRING and decode ASN1 structure if zbuf set zero buffer
1266f9291ceSJung-uk Kim  * after use.
12774664626SKris Kennaway  */
12874664626SKris Kennaway 
PKCS12_item_decrypt_d2i_ex(const X509_ALGOR * algor,const ASN1_ITEM * it,const char * pass,int passlen,const ASN1_OCTET_STRING * oct,int zbuf,OSSL_LIB_CTX * libctx,const char * propq)129b077aed3SPierre Pronchery void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
1306f9291ceSJung-uk Kim                                  const char *pass, int passlen,
131b077aed3SPierre Pronchery                                  const ASN1_OCTET_STRING *oct, int zbuf,
132b077aed3SPierre Pronchery                                  OSSL_LIB_CTX *libctx,
133b077aed3SPierre Pronchery                                  const char *propq)
13474664626SKris Kennaway {
135b077aed3SPierre Pronchery     unsigned char *out = NULL;
1363b4e3dcbSSimon L. B. Nielsen     const unsigned char *p;
1375c87c606SMark Murray     void *ret;
138b077aed3SPierre Pronchery     int outlen = 0;
13974664626SKris Kennaway 
140b077aed3SPierre Pronchery     if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, oct->data, oct->length,
141b077aed3SPierre Pronchery                              &out, &outlen, 0, libctx, propq))
14274664626SKris Kennaway         return NULL;
14374664626SKris Kennaway     p = out;
144b077aed3SPierre Pronchery     OSSL_TRACE_BEGIN(PKCS12_DECRYPT) {
145b077aed3SPierre Pronchery         BIO_printf(trc_out, "\n");
146b077aed3SPierre Pronchery         BIO_dump(trc_out, out, outlen);
147b077aed3SPierre Pronchery         BIO_printf(trc_out, "\n");
148b077aed3SPierre Pronchery     } OSSL_TRACE_END(PKCS12_DECRYPT);
1495c87c606SMark Murray     ret = ASN1_item_d2i(NULL, &p, outlen, it);
1506f9291ceSJung-uk Kim     if (zbuf)
1516f9291ceSJung-uk Kim         OPENSSL_cleanse(out, outlen);
1526f9291ceSJung-uk Kim     if (!ret)
153b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
154ddd58736SKris Kennaway     OPENSSL_free(out);
15574664626SKris Kennaway     return ret;
15674664626SKris Kennaway }
15774664626SKris Kennaway 
PKCS12_item_decrypt_d2i(const X509_ALGOR * algor,const ASN1_ITEM * it,const char * pass,int passlen,const ASN1_OCTET_STRING * oct,int zbuf)158b077aed3SPierre Pronchery void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
159b077aed3SPierre Pronchery                               const char *pass, int passlen,
160b077aed3SPierre Pronchery                               const ASN1_OCTET_STRING *oct, int zbuf)
161b077aed3SPierre Pronchery {
162b077aed3SPierre Pronchery     return PKCS12_item_decrypt_d2i_ex(algor, it, pass, passlen, oct, zbuf,
163b077aed3SPierre Pronchery                                       NULL, NULL);
164b077aed3SPierre Pronchery }
165b077aed3SPierre Pronchery 
1666f9291ceSJung-uk Kim /*
1676f9291ceSJung-uk Kim  * Encode ASN1 structure and encrypt, return OCTET STRING if zbuf set zero
1686f9291ceSJung-uk Kim  * encoding.
16974664626SKris Kennaway  */
17074664626SKris Kennaway 
PKCS12_item_i2d_encrypt_ex(X509_ALGOR * algor,const ASN1_ITEM * it,const char * pass,int passlen,void * obj,int zbuf,OSSL_LIB_CTX * ctx,const char * propq)171b077aed3SPierre Pronchery ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor,
1726f9291ceSJung-uk Kim                                               const ASN1_ITEM *it,
17374664626SKris Kennaway                                               const char *pass, int passlen,
174b077aed3SPierre Pronchery                                               void *obj, int zbuf,
175b077aed3SPierre Pronchery                                               OSSL_LIB_CTX *ctx,
176b077aed3SPierre Pronchery                                               const char *propq)
17774664626SKris Kennaway {
1787bded2dbSJung-uk Kim     ASN1_OCTET_STRING *oct = NULL;
1795c87c606SMark Murray     unsigned char *in = NULL;
18074664626SKris Kennaway     int inlen;
181e71b7053SJung-uk Kim 
182e71b7053SJung-uk Kim     if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
183b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
1847bded2dbSJung-uk Kim         goto err;
18574664626SKris Kennaway     }
1865c87c606SMark Murray     inlen = ASN1_item_i2d(obj, &in, it);
1875c87c606SMark Murray     if (!in) {
188b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCODE_ERROR);
1897bded2dbSJung-uk Kim         goto err;
19074664626SKris Kennaway     }
191b077aed3SPierre Pronchery     if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, in, inlen, &oct->data,
192b077aed3SPierre Pronchery                              &oct->length, 1, ctx, propq)) {
193b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR);
194ddd58736SKris Kennaway         OPENSSL_free(in);
1957bded2dbSJung-uk Kim         goto err;
19674664626SKris Kennaway     }
1976f9291ceSJung-uk Kim     if (zbuf)
1986f9291ceSJung-uk Kim         OPENSSL_cleanse(in, inlen);
199ddd58736SKris Kennaway     OPENSSL_free(in);
20074664626SKris Kennaway     return oct;
2017bded2dbSJung-uk Kim  err:
2027bded2dbSJung-uk Kim     ASN1_OCTET_STRING_free(oct);
2037bded2dbSJung-uk Kim     return NULL;
20474664626SKris Kennaway }
205b077aed3SPierre Pronchery 
PKCS12_item_i2d_encrypt(X509_ALGOR * algor,const ASN1_ITEM * it,const char * pass,int passlen,void * obj,int zbuf)206b077aed3SPierre Pronchery ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
207b077aed3SPierre Pronchery                                            const ASN1_ITEM *it,
208b077aed3SPierre Pronchery                                            const char *pass, int passlen,
209b077aed3SPierre Pronchery                                            void *obj, int zbuf)
210b077aed3SPierre Pronchery {
211b077aed3SPierre Pronchery     return PKCS12_item_i2d_encrypt_ex(algor, it, pass, passlen, obj, zbuf, NULL, NULL);
212b077aed3SPierre Pronchery }
213