| // SPDX-License-Identifier: BSD-2-Clause |
| /* LibTomCrypt, modular cryptographic library -- Tom St Denis |
| * |
| * LibTomCrypt is a library that provides various cryptographic |
| * algorithms in a highly modular and flexible manner. |
| * |
| * The library is free for all purposes without any express |
| * guarantee it works. |
| */ |
| #include "tomcrypt_private.h" |
| |
| #ifdef LTC_PBES |
| |
| /** |
| Decrypt Data encrypted via either PBES1 or PBES2 |
| |
| @param arg The according PBES parameters |
| @param dec_data [out] The decrypted data |
| @param dec_size [in/out] The length of the encrypted resp. decrypted data |
| @return CRYPT_OK on success |
| */ |
| int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size) |
| { |
| int err, hid, cid; |
| unsigned char k[32], *iv; |
| unsigned long klen, keylen, dlen; |
| long diff; |
| symmetric_CBC cbc; |
| |
| LTC_ARGCHK(arg != NULL); |
| LTC_ARGCHK(arg->type.kdf != NULL); |
| LTC_ARGCHK(dec_data != NULL); |
| LTC_ARGCHK(dec_size != NULL); |
| |
| hid = find_hash(arg->type.h); |
| if (hid == -1) return CRYPT_INVALID_HASH; |
| cid = find_cipher(arg->type.c); |
| if (cid == -1) return CRYPT_INVALID_CIPHER; |
| |
| klen = arg->type.keylen; |
| |
| /* RC2 special case */ |
| if (arg->key_bits != 0) { |
| /* We can't handle odd lengths of Key Bits */ |
| if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE; |
| /* Internally we use bytes, not bits */ |
| klen = arg->key_bits / 8; |
| } |
| keylen = klen; |
| |
| if (arg->iv != NULL) { |
| iv = arg->iv->data; |
| } else { |
| iv = k + klen; |
| klen += arg->type.blocklen; |
| } |
| |
| if (klen > sizeof(k)) return CRYPT_INVALID_ARG; |
| |
| 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; |
| if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR; |
| if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR; |
| if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR; |
| dlen = arg->enc_data->size; |
| if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR; |
| diff = (long)arg->enc_data->size - (long)dlen; |
| if ((diff <= 0) || (diff > cipher_descriptor[cid]->block_length)) { |
| err = CRYPT_PK_INVALID_PADDING; |
| goto LBL_ERROR; |
| } |
| *dec_size = dlen; |
| return CRYPT_OK; |
| |
| LBL_ERROR: |
| zeromem(k, sizeof(k)); |
| zeromem(dec_data, *dec_size); |
| return err; |
| } |
| |
| #endif |
| |
| /* ref: $Format:%D$ */ |
| /* git commit: $Format:%H$ */ |
| /* commit time: $Format:%ai$ */ |