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