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