107 lines
3.4 KiB
C
107 lines
3.4 KiB
C
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
|
|
/* SPDX-License-Identifier: Unlicense */
|
|
#include "tomcrypt_private.h"
|
|
|
|
#ifdef LTC_PKCS_8
|
|
|
|
/**
|
|
PKCS#8 decrypt if necessary & flexi-decode
|
|
|
|
@param in Pointer to the ASN.1 encoded input data
|
|
@param inlen Length of the input data
|
|
@param pwd Pointer to the password that was used when encrypting
|
|
@param pwdlen Length of the password
|
|
@param decoded_list Pointer to a pointer for the flexi-decoded list
|
|
@return CRYPT_OK on success
|
|
*/
|
|
int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
|
|
const password_ctx *pw_ctx,
|
|
ltc_asn1_list **decoded_list)
|
|
{
|
|
unsigned long len = inlen;
|
|
unsigned long dec_size;
|
|
unsigned char *dec_data = NULL;
|
|
ltc_asn1_list *l = NULL;
|
|
int err;
|
|
pbes_arg pbes;
|
|
|
|
LTC_ARGCHK(in != NULL);
|
|
LTC_ARGCHK(decoded_list != NULL);
|
|
|
|
XMEMSET(&pbes, 0, sizeof(pbes));
|
|
|
|
*decoded_list = NULL;
|
|
if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
|
|
/* the following "if" detects whether it is encrypted or not */
|
|
/* PKCS8 Setup
|
|
* 0:d=0 hl=4 l= 380 cons: SEQUENCE
|
|
* 4:d=1 hl=2 l= 78 cons: SEQUENCE
|
|
* 6:d=2 hl=2 l= 9 prim: OBJECT :OID indicating PBES1 or PBES2 (== *lalgoid)
|
|
* 17:d=2 hl=2 l= 65 cons: SEQUENCE
|
|
* Stuff in between is dependent on whether it's PBES1 or PBES2
|
|
* 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
|
|
*/
|
|
if (l->type == LTC_ASN1_SEQUENCE &&
|
|
LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) &&
|
|
LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) &&
|
|
LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) &&
|
|
LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) {
|
|
ltc_asn1_list *lalgoid = l->child->child;
|
|
|
|
if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) {
|
|
err = CRYPT_PW_CTX_MISSING;
|
|
goto LBL_DONE;
|
|
}
|
|
|
|
if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) {
|
|
/* Successfully extracted PBES1 parameters */
|
|
} else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) {
|
|
/* Successfully extracted PBES2 parameters */
|
|
} else {
|
|
/* unsupported encryption */
|
|
err = CRYPT_INVALID_PACKET;
|
|
goto LBL_DONE;
|
|
}
|
|
|
|
if (pw_ctx->callback(&pbes.pw.pw, &pbes.pw.l, pw_ctx->userdata)) {
|
|
err = CRYPT_ERROR;
|
|
goto LBL_DONE;
|
|
}
|
|
|
|
pbes.enc_data = l->child->next;
|
|
|
|
dec_size = pbes.enc_data->size;
|
|
if ((dec_data = XMALLOC(dec_size)) == NULL) {
|
|
err = CRYPT_MEM;
|
|
goto LBL_DONE;
|
|
}
|
|
|
|
if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE;
|
|
|
|
der_free_sequence_flexi(l);
|
|
l = NULL;
|
|
err = der_decode_sequence_flexi(dec_data, &dec_size, &l);
|
|
if (err != CRYPT_OK) goto LBL_DONE;
|
|
*decoded_list = l;
|
|
}
|
|
else {
|
|
/* not encrypted */
|
|
err = CRYPT_OK;
|
|
*decoded_list = l;
|
|
}
|
|
/* Set l to NULL so it won't be free'd */
|
|
l = NULL;
|
|
}
|
|
|
|
LBL_DONE:
|
|
if (dec_data) {
|
|
zeromem(dec_data, dec_size);
|
|
XFREE(dec_data);
|
|
}
|
|
password_free(&pbes.pw, pw_ctx);
|
|
if (l) der_free_sequence_flexi(l);
|
|
return err;
|
|
}
|
|
|
|
#endif
|