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