1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10 #include "tomcrypt_private.h"
11
12 #ifdef LTC_PBES
13
14 /**
15 Decrypt Data encrypted via either PBES1 or PBES2
16
17 @param arg The according PBES parameters
18 @param dec_data [out] The decrypted data
19 @param dec_size [in/out] The length of the encrypted resp. decrypted data
20 @return CRYPT_OK on success
21 */
pbes_decrypt(const pbes_arg * arg,unsigned char * dec_data,unsigned long * dec_size)22 int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size)
23 {
24 int err, hid, cid;
25 unsigned char k[32], *iv;
26 unsigned long klen, keylen, dlen;
27 long diff;
28 symmetric_CBC cbc;
29
30 LTC_ARGCHK(arg != NULL);
31 LTC_ARGCHK(arg->type.kdf != NULL);
32 LTC_ARGCHK(dec_data != NULL);
33 LTC_ARGCHK(dec_size != NULL);
34
35 hid = find_hash(arg->type.h);
36 if (hid == -1) return CRYPT_INVALID_HASH;
37 cid = find_cipher(arg->type.c);
38 if (cid == -1) return CRYPT_INVALID_CIPHER;
39
40 klen = arg->type.keylen;
41
42 /* RC2 special case */
43 if (arg->key_bits != 0) {
44 /* We can't handle odd lengths of Key Bits */
45 if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE;
46 /* Internally we use bytes, not bits */
47 klen = arg->key_bits / 8;
48 }
49 keylen = klen;
50
51 if (arg->iv != NULL) {
52 iv = arg->iv->data;
53 } else {
54 iv = k + klen;
55 klen += arg->type.blocklen;
56 }
57
58 if (klen > sizeof(k)) return CRYPT_INVALID_ARG;
59
60 if ((err = arg->type.kdf(arg->pwd, arg->pwdlen, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
61 if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
62 if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
63 if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
64 dlen = arg->enc_data->size;
65 if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR;
66 diff = (long)arg->enc_data->size - (long)dlen;
67 if ((diff <= 0) || (diff > cipher_descriptor[cid]->block_length)) {
68 err = CRYPT_PK_INVALID_PADDING;
69 goto LBL_ERROR;
70 }
71 *dec_size = dlen;
72 return CRYPT_OK;
73
74 LBL_ERROR:
75 zeromem(k, sizeof(k));
76 zeromem(dec_data, *dec_size);
77 return err;
78 }
79
80 #endif
81
82 /* ref: $Format:%D$ */
83 /* git commit: $Format:%H$ */
84 /* commit time: $Format:%ai$ */
85